@basis-theory/web-elements 3.0.0-beta.4 → 3.0.0-beta.6
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/dist/.vite/manifest.json +22 -11
- package/dist/basis-theory-sdk.es.js +2 -2
- package/dist/basis-theory-sdk.umd.js +1 -1
- package/dist/basis-theory-sdk.umd.js.map +1 -1
- package/dist/{create-card-B5zEHyRg.js → create-card-C0MwL3Ou.js} +21 -14
- package/dist/create-card-C0MwL3Ou.js.map +1 -0
- package/dist/create-card-display-DscvxIs4.js +291 -0
- package/dist/create-card-display-DscvxIs4.js.map +1 -0
- package/dist/{create-copy-button-DrAz8g0m.js → create-copy-button-DlJ3VvAn.js} +40 -12
- package/dist/create-copy-button-DlJ3VvAn.js.map +1 -0
- package/dist/{index-BOedIhUN.js → index-DPhSs28B.js} +432 -121
- package/dist/index-DPhSs28B.js.map +1 -0
- package/dist/index.d.ts +1133 -0
- package/dist/loader/basis-theory.min.js +1 -1
- package/dist/sri.json +9 -9
- package/dist/stats.html +1 -1
- package/package.json +12 -12
- package/dist/api-client/src/api-client.d.ts +0 -11
- package/dist/api-client/src/api-client.d.ts.map +0 -1
- package/dist/api-client/src/bin-lookup-transform.d.ts +0 -35
- package/dist/api-client/src/bin-lookup-transform.d.ts.map +0 -1
- package/dist/api-client/src/http-client.d.ts +0 -24
- package/dist/api-client/src/http-client.d.ts.map +0 -1
- package/dist/api-client/src/index.d.ts +0 -9
- package/dist/api-client/src/index.d.ts.map +0 -1
- package/dist/api-client/src/services/sessions.d.ts +0 -19
- package/dist/api-client/src/services/sessions.d.ts.map +0 -1
- package/dist/api-client/src/services/token-intents.d.ts +0 -17
- package/dist/api-client/src/services/token-intents.d.ts.map +0 -1
- package/dist/api-client/src/services/tokens.d.ts +0 -19
- package/dist/api-client/src/services/tokens.d.ts.map +0 -1
- package/dist/api-client/src/types.d.ts +0 -421
- package/dist/api-client/src/types.d.ts.map +0 -1
- package/dist/create-card-B5zEHyRg.js.map +0 -1
- package/dist/create-copy-button-DrAz8g0m.js.map +0 -1
- package/dist/index-BOedIhUN.js.map +0 -1
- package/dist/postmessage/src/client.d.ts +0 -7
- package/dist/postmessage/src/client.d.ts.map +0 -1
- package/dist/postmessage/src/event-map.d.ts +0 -139
- package/dist/postmessage/src/event-map.d.ts.map +0 -1
- package/dist/postmessage/src/index.d.ts +0 -9
- package/dist/postmessage/src/index.d.ts.map +0 -1
- package/dist/postmessage/src/server.d.ts +0 -11
- package/dist/postmessage/src/server.d.ts.map +0 -1
- package/dist/postmessage/src/types.d.ts +0 -75
- package/dist/postmessage/src/types.d.ts.map +0 -1
- package/dist/shared/src/api-url-resolver.d.ts +0 -22
- package/dist/shared/src/api-url-resolver.d.ts.map +0 -1
- package/dist/shared/src/debug-logger.d.ts +0 -16
- package/dist/shared/src/debug-logger.d.ts.map +0 -1
- package/dist/shared/src/deep-sanitization.d.ts +0 -24
- package/dist/shared/src/deep-sanitization.d.ts.map +0 -1
- package/dist/shared/src/errors.d.ts +0 -93
- package/dist/shared/src/errors.d.ts.map +0 -1
- package/dist/shared/src/generate-id.d.ts +0 -13
- package/dist/shared/src/generate-id.d.ts.map +0 -1
- package/dist/shared/src/index.d.ts +0 -14
- package/dist/shared/src/index.d.ts.map +0 -1
- package/dist/shared/src/logger-context.d.ts +0 -25
- package/dist/shared/src/logger-context.d.ts.map +0 -1
- package/dist/shared/src/proxy-validation.d.ts +0 -93
- package/dist/shared/src/proxy-validation.d.ts.map +0 -1
- package/dist/web-elements/src/BasisTheory.d.ts +0 -47
- package/dist/web-elements/src/BasisTheory.d.ts.map +0 -1
- package/dist/web-elements/src/basis-theory.d.ts +0 -85
- package/dist/web-elements/src/basis-theory.d.ts.map +0 -1
- package/dist/web-elements/src/elements/create-card-number.d.ts +0 -15
- package/dist/web-elements/src/elements/create-card-number.d.ts.map +0 -1
- package/dist/web-elements/src/elements/create-card.d.ts +0 -50
- package/dist/web-elements/src/elements/create-card.d.ts.map +0 -1
- package/dist/web-elements/src/elements/create-copy-button.d.ts +0 -19
- package/dist/web-elements/src/elements/create-copy-button.d.ts.map +0 -1
- package/dist/web-elements/src/elements/create-cvv.d.ts +0 -11
- package/dist/web-elements/src/elements/create-cvv.d.ts.map +0 -1
- package/dist/web-elements/src/elements/create-expiry.d.ts +0 -11
- package/dist/web-elements/src/elements/create-expiry.d.ts.map +0 -1
- package/dist/web-elements/src/elements/create-text.d.ts +0 -14
- package/dist/web-elements/src/elements/create-text.d.ts.map +0 -1
- package/dist/web-elements/src/index.d.ts +0 -27
- package/dist/web-elements/src/index.d.ts.map +0 -1
- package/dist/web-elements/src/mounter/create-mounter.d.ts +0 -11
- package/dist/web-elements/src/mounter/create-mounter.d.ts.map +0 -1
- package/dist/web-elements/src/theme/default-theme.d.ts +0 -22
- package/dist/web-elements/src/theme/default-theme.d.ts.map +0 -1
- package/dist/web-elements/src/theme/inject-theme-dark.d.ts +0 -13
- package/dist/web-elements/src/theme/inject-theme-dark.d.ts.map +0 -1
- package/dist/web-elements/src/theme/inject-theme.d.ts +0 -20
- package/dist/web-elements/src/theme/inject-theme.d.ts.map +0 -1
- package/dist/web-elements/src/types/events.d.ts +0 -165
- package/dist/web-elements/src/types/events.d.ts.map +0 -1
- package/dist/web-elements/src/types/theme.d.ts +0 -91
- package/dist/web-elements/src/types/theme.d.ts.map +0 -1
- package/dist/web-elements/src/types.d.ts +0 -667
- package/dist/web-elements/src/types.d.ts.map +0 -1
- package/dist/web-elements/src/utils/create-event-dispatcher.d.ts +0 -47
- package/dist/web-elements/src/utils/create-event-dispatcher.d.ts.map +0 -1
- package/dist/web-elements/src/utils/create-iframe.d.ts +0 -10
- package/dist/web-elements/src/utils/create-iframe.d.ts.map +0 -1
- package/dist/web-elements/src/utils/resolve-element-references.d.ts +0 -20
- package/dist/web-elements/src/utils/resolve-element-references.d.ts.map +0 -1
- package/dist/web-elements/src/utils/validate-element-options.d.ts +0 -11
- package/dist/web-elements/src/utils/validate-element-options.d.ts.map +0 -1
- package/dist/web-elements/src/utils/validate-sdk-config.d.ts +0 -15
- package/dist/web-elements/src/utils/validate-sdk-config.d.ts.map +0 -1
- package/dist/web-elements/src/utils/warn-unknown-keys.d.ts +0 -15
- package/dist/web-elements/src/utils/warn-unknown-keys.d.ts.map +0 -1
- package/dist/web-elements/src/version.d.ts +0 -25
- package/dist/web-elements/src/version.d.ts.map +0 -1
|
@@ -15,7 +15,9 @@ const REDACT_PATTERNS = [
|
|
|
15
15
|
/secret/i,
|
|
16
16
|
/token/i,
|
|
17
17
|
/ssn/i,
|
|
18
|
-
/track/i
|
|
18
|
+
/track/i,
|
|
19
|
+
/session_key/i,
|
|
20
|
+
/^apikey$/i
|
|
19
21
|
];
|
|
20
22
|
const isPANField = (key) => {
|
|
21
23
|
return PAN_PATTERNS.some((pattern) => pattern.test(key));
|
|
@@ -140,6 +142,16 @@ const createDebugLogger = (packageName, enabled) => {
|
|
|
140
142
|
console.log(`🔍 [${timestamp}] [${packageName}] ${action}`, sanitized);
|
|
141
143
|
};
|
|
142
144
|
};
|
|
145
|
+
const generateId = () => {
|
|
146
|
+
if (typeof crypto !== "undefined" && crypto.randomUUID) {
|
|
147
|
+
return crypto.randomUUID();
|
|
148
|
+
}
|
|
149
|
+
const random = () => Math.random().toString(36).substring(2);
|
|
150
|
+
const randomPart = (random() + random() + random() + random()).substring(0, 32);
|
|
151
|
+
return `${randomPart.substring(0, 8)}-${randomPart.substring(8, 12)}-${randomPart.substring(12, 16)}-${randomPart.substring(16, 20)}-${randomPart.substring(20, 32)}`;
|
|
152
|
+
};
|
|
153
|
+
const log = (action, metadata) => {
|
|
154
|
+
};
|
|
143
155
|
const createBasisTheoryError = (code, message, details) => {
|
|
144
156
|
const error = new Error(message);
|
|
145
157
|
error.name = "BasisTheoryError";
|
|
@@ -183,8 +195,6 @@ const ConfigurationError = (message, details) => {
|
|
|
183
195
|
error.name = "ConfigurationError";
|
|
184
196
|
return error;
|
|
185
197
|
};
|
|
186
|
-
const log = (action, metadata) => {
|
|
187
|
-
};
|
|
188
198
|
const ALLOWED_PROXY_SCHEMES = /* @__PURE__ */ new Set(["https:"]);
|
|
189
199
|
const ALLOWED_METHODS = /* @__PURE__ */ new Set([
|
|
190
200
|
"GET",
|
|
@@ -463,9 +473,10 @@ const createPostMessageClient = (iframe, config) => {
|
|
|
463
473
|
try {
|
|
464
474
|
callback(payload);
|
|
465
475
|
} catch (err) {
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
476
|
+
log2("Error in event subscriber", {
|
|
477
|
+
type,
|
|
478
|
+
error: err.message
|
|
479
|
+
});
|
|
469
480
|
}
|
|
470
481
|
});
|
|
471
482
|
} else if (!nonce) {
|
|
@@ -477,9 +488,9 @@ const createPostMessageClient = (iframe, config) => {
|
|
|
477
488
|
};
|
|
478
489
|
window.addEventListener("message", handleMessage);
|
|
479
490
|
const retryConfig = typeof config.retries === "number" ? { ...DEFAULT_RETRY_CONFIG, maxRetries: config.retries } : typeof config.retries === "object" ? config.retries : DEFAULT_RETRY_CONFIG;
|
|
480
|
-
const sendRequestOnce = (type, payload) => {
|
|
491
|
+
const sendRequestOnce = (type, payload, transfer) => {
|
|
481
492
|
return new Promise((resolve, reject) => {
|
|
482
|
-
const nonce =
|
|
493
|
+
const nonce = generateId();
|
|
483
494
|
const timestamp = Date.now();
|
|
484
495
|
if (!iframe.contentWindow) {
|
|
485
496
|
reject(BasisTheoryError("IFRAME_NOT_READY", "Iframe not ready"));
|
|
@@ -491,15 +502,21 @@ const createPostMessageClient = (iframe, config) => {
|
|
|
491
502
|
}, config.timeout || 5e3);
|
|
492
503
|
pendingRequests.set(nonce, { resolve, reject, timeout, timestamp });
|
|
493
504
|
log2("Sending request", { type, nonce });
|
|
494
|
-
|
|
505
|
+
const message = { type, nonce, timestamp, payload };
|
|
506
|
+
if (transfer == null ? void 0 : transfer.length) {
|
|
507
|
+
iframe.contentWindow.postMessage(message, config.targetOrigin, transfer);
|
|
508
|
+
} else {
|
|
509
|
+
iframe.contentWindow.postMessage(message, config.targetOrigin);
|
|
510
|
+
}
|
|
495
511
|
});
|
|
496
512
|
};
|
|
497
513
|
const sendRequest = async (type, payload, options) => {
|
|
498
|
-
|
|
514
|
+
var _a;
|
|
515
|
+
const maxRetries = ((_a = options == null ? void 0 : options.transfer) == null ? void 0 : _a.length) ? 0 : (options == null ? void 0 : options.retries) !== void 0 ? options.retries : retryConfig.maxRetries;
|
|
499
516
|
let lastError = null;
|
|
500
517
|
for (let attempt = 0; attempt <= maxRetries; attempt++) {
|
|
501
518
|
try {
|
|
502
|
-
return await sendRequestOnce(type, payload);
|
|
519
|
+
return await sendRequestOnce(type, payload, options == null ? void 0 : options.transfer);
|
|
503
520
|
} catch (error) {
|
|
504
521
|
lastError = error;
|
|
505
522
|
const errorMessage = error.message;
|
|
@@ -597,6 +614,54 @@ const createMounter = () => {
|
|
|
597
614
|
}
|
|
598
615
|
};
|
|
599
616
|
};
|
|
617
|
+
const CMD_REGISTER_ELEMENT = "CMD_REGISTER_ELEMENT";
|
|
618
|
+
const CMD_BIND_ELEMENT_PORT = "CMD_BIND_ELEMENT_PORT";
|
|
619
|
+
const CMD_BIND_COORDINATOR_PORT = "CMD_BIND_COORDINATOR_PORT";
|
|
620
|
+
const bindCoordinatorPort = async ({
|
|
621
|
+
elementId,
|
|
622
|
+
elementType,
|
|
623
|
+
client,
|
|
624
|
+
coordinatorRequest
|
|
625
|
+
}) => {
|
|
626
|
+
await coordinatorRequest(CMD_REGISTER_ELEMENT, {
|
|
627
|
+
elementId,
|
|
628
|
+
type: elementType
|
|
629
|
+
});
|
|
630
|
+
const channel = new MessageChannel();
|
|
631
|
+
const coordinatorBind = await coordinatorRequest(
|
|
632
|
+
CMD_BIND_ELEMENT_PORT,
|
|
633
|
+
{ elementId },
|
|
634
|
+
{ retries: 0, transfer: [channel.port2] }
|
|
635
|
+
);
|
|
636
|
+
if (!(coordinatorBind == null ? void 0 : coordinatorBind.success)) {
|
|
637
|
+
channel.port1.close();
|
|
638
|
+
throw ElementError(
|
|
639
|
+
`Coordinator rejected the element port (${(coordinatorBind == null ? void 0 : coordinatorBind.error) ?? "UNKNOWN"})`,
|
|
640
|
+
elementId,
|
|
641
|
+
{ elementType }
|
|
642
|
+
);
|
|
643
|
+
}
|
|
644
|
+
const elementBind = await client.sendRequest(
|
|
645
|
+
CMD_BIND_COORDINATOR_PORT,
|
|
646
|
+
{ elementId },
|
|
647
|
+
{ retries: 0, transfer: [channel.port1] }
|
|
648
|
+
).catch((error) => {
|
|
649
|
+
log("Failed to hand coordinator port to element", {
|
|
650
|
+
error: error.message
|
|
651
|
+
});
|
|
652
|
+
return { success: false, error: error.message };
|
|
653
|
+
});
|
|
654
|
+
if (!(elementBind == null ? void 0 : elementBind.success)) {
|
|
655
|
+
await coordinatorRequest("CMD_BROADCAST_ELEMENT_UNMOUNT", {
|
|
656
|
+
elementId
|
|
657
|
+
}).catch(() => void 0);
|
|
658
|
+
throw ElementError(
|
|
659
|
+
`Element rejected the coordinator port (${(elementBind == null ? void 0 : elementBind.error) ?? "UNKNOWN"})`,
|
|
660
|
+
elementId,
|
|
661
|
+
{ elementType }
|
|
662
|
+
);
|
|
663
|
+
}
|
|
664
|
+
};
|
|
600
665
|
const createIframe = (config) => {
|
|
601
666
|
const iframe = document.createElement("iframe");
|
|
602
667
|
iframe.src = config.src;
|
|
@@ -709,7 +774,7 @@ const createEventDispatcher = (config) => {
|
|
|
709
774
|
dispatchError
|
|
710
775
|
};
|
|
711
776
|
};
|
|
712
|
-
const createCardNumberElement = (apiKey, sdkConfig, options = {}, coordinatorElementId, ensureCoordinatorReady, notifyCoordinatorElementUnmount) => {
|
|
777
|
+
const createCardNumberElement = (apiKey, sdkConfig, options = {}, coordinatorElementId, ensureCoordinatorReady, notifyCoordinatorElementUnmount, coordinatorRequest) => {
|
|
713
778
|
let iframe = null;
|
|
714
779
|
let client = null;
|
|
715
780
|
let mounter = null;
|
|
@@ -743,6 +808,9 @@ const createCardNumberElement = (apiKey, sdkConfig, options = {}, coordinatorEle
|
|
|
743
808
|
get mounted() {
|
|
744
809
|
return isMounted;
|
|
745
810
|
},
|
|
811
|
+
get loaded() {
|
|
812
|
+
return isMounted;
|
|
813
|
+
},
|
|
746
814
|
mount: async (selector) => {
|
|
747
815
|
if (isMounted) {
|
|
748
816
|
throw ElementError("Element is already mounted");
|
|
@@ -800,6 +868,12 @@ const createCardNumberElement = (apiKey, sdkConfig, options = {}, coordinatorEle
|
|
|
800
868
|
try {
|
|
801
869
|
await ensureCoordinatorReady();
|
|
802
870
|
await readyPromise;
|
|
871
|
+
await bindCoordinatorPort({
|
|
872
|
+
elementId: id,
|
|
873
|
+
elementType: type,
|
|
874
|
+
client,
|
|
875
|
+
coordinatorRequest
|
|
876
|
+
});
|
|
803
877
|
await client.sendRequest("CMD_SET_CONFIG", {
|
|
804
878
|
elementId: id,
|
|
805
879
|
// Include element ID for validation
|
|
@@ -928,7 +1002,7 @@ const createCardNumberElement = (apiKey, sdkConfig, options = {}, coordinatorEle
|
|
|
928
1002
|
}
|
|
929
1003
|
};
|
|
930
1004
|
};
|
|
931
|
-
const createCVVElement = (apiKey, sdkConfig, options = {}, coordinatorElementId, ensureCoordinatorReady, notifyCoordinatorElementUnmount) => {
|
|
1005
|
+
const createCVVElement = (apiKey, sdkConfig, options = {}, coordinatorElementId, ensureCoordinatorReady, notifyCoordinatorElementUnmount, coordinatorRequest) => {
|
|
932
1006
|
let iframe = null;
|
|
933
1007
|
let client = null;
|
|
934
1008
|
let mounter = null;
|
|
@@ -954,6 +1028,9 @@ const createCVVElement = (apiKey, sdkConfig, options = {}, coordinatorElementId,
|
|
|
954
1028
|
get mounted() {
|
|
955
1029
|
return isMounted;
|
|
956
1030
|
},
|
|
1031
|
+
get loaded() {
|
|
1032
|
+
return isMounted;
|
|
1033
|
+
},
|
|
957
1034
|
mount: async (selector) => {
|
|
958
1035
|
if (isMounted) {
|
|
959
1036
|
throw ElementError("Element is already mounted", id);
|
|
@@ -1008,6 +1085,12 @@ const createCVVElement = (apiKey, sdkConfig, options = {}, coordinatorElementId,
|
|
|
1008
1085
|
try {
|
|
1009
1086
|
await ensureCoordinatorReady();
|
|
1010
1087
|
await readyPromise;
|
|
1088
|
+
await bindCoordinatorPort({
|
|
1089
|
+
elementId: id,
|
|
1090
|
+
elementType: type,
|
|
1091
|
+
client,
|
|
1092
|
+
coordinatorRequest
|
|
1093
|
+
});
|
|
1011
1094
|
await client.sendRequest("CMD_SET_CONFIG", {
|
|
1012
1095
|
elementId: id,
|
|
1013
1096
|
// Include element ID for validation
|
|
@@ -1118,7 +1201,7 @@ const createCVVElement = (apiKey, sdkConfig, options = {}, coordinatorElementId,
|
|
|
1118
1201
|
}
|
|
1119
1202
|
};
|
|
1120
1203
|
};
|
|
1121
|
-
const createExpiryElement = (apiKey, sdkConfig, options = {}, coordinatorElementId, ensureCoordinatorReady, notifyCoordinatorElementUnmount) => {
|
|
1204
|
+
const createExpiryElement = (apiKey, sdkConfig, options = {}, coordinatorElementId, ensureCoordinatorReady, notifyCoordinatorElementUnmount, coordinatorRequest) => {
|
|
1122
1205
|
let iframe = null;
|
|
1123
1206
|
let client = null;
|
|
1124
1207
|
let mounter = null;
|
|
@@ -1144,6 +1227,9 @@ const createExpiryElement = (apiKey, sdkConfig, options = {}, coordinatorElement
|
|
|
1144
1227
|
get mounted() {
|
|
1145
1228
|
return isMounted;
|
|
1146
1229
|
},
|
|
1230
|
+
get loaded() {
|
|
1231
|
+
return isMounted;
|
|
1232
|
+
},
|
|
1147
1233
|
mount: async (selector) => {
|
|
1148
1234
|
if (isMounted) {
|
|
1149
1235
|
throw ElementError("Element is already mounted", id);
|
|
@@ -1198,6 +1284,12 @@ const createExpiryElement = (apiKey, sdkConfig, options = {}, coordinatorElement
|
|
|
1198
1284
|
try {
|
|
1199
1285
|
await ensureCoordinatorReady();
|
|
1200
1286
|
await readyPromise;
|
|
1287
|
+
await bindCoordinatorPort({
|
|
1288
|
+
elementId: id,
|
|
1289
|
+
elementType: type,
|
|
1290
|
+
client,
|
|
1291
|
+
coordinatorRequest
|
|
1292
|
+
});
|
|
1201
1293
|
await client.sendRequest("CMD_SET_CONFIG", {
|
|
1202
1294
|
elementId: id,
|
|
1203
1295
|
// Include element ID for validation
|
|
@@ -1304,7 +1396,7 @@ const createExpiryElement = (apiKey, sdkConfig, options = {}, coordinatorElement
|
|
|
1304
1396
|
}
|
|
1305
1397
|
};
|
|
1306
1398
|
};
|
|
1307
|
-
const createTextElement = (apiKey, sdkConfig, options = {}, coordinatorElementId, ensureCoordinatorReady, notifyCoordinatorElementUnmount) => {
|
|
1399
|
+
const createTextElement = (apiKey, sdkConfig, options = {}, coordinatorElementId, ensureCoordinatorReady, notifyCoordinatorElementUnmount, coordinatorRequest) => {
|
|
1308
1400
|
let iframe = null;
|
|
1309
1401
|
let client = null;
|
|
1310
1402
|
let mounter = null;
|
|
@@ -1337,6 +1429,9 @@ const createTextElement = (apiKey, sdkConfig, options = {}, coordinatorElementId
|
|
|
1337
1429
|
get mounted() {
|
|
1338
1430
|
return isMounted;
|
|
1339
1431
|
},
|
|
1432
|
+
get loaded() {
|
|
1433
|
+
return isMounted;
|
|
1434
|
+
},
|
|
1340
1435
|
mount: async (selector) => {
|
|
1341
1436
|
if (isMounted) {
|
|
1342
1437
|
throw ElementError("Element is already mounted", id);
|
|
@@ -1391,6 +1486,12 @@ const createTextElement = (apiKey, sdkConfig, options = {}, coordinatorElementId
|
|
|
1391
1486
|
try {
|
|
1392
1487
|
await ensureCoordinatorReady();
|
|
1393
1488
|
await readyPromise;
|
|
1489
|
+
await bindCoordinatorPort({
|
|
1490
|
+
elementId: id,
|
|
1491
|
+
elementType: type,
|
|
1492
|
+
client,
|
|
1493
|
+
coordinatorRequest
|
|
1494
|
+
});
|
|
1394
1495
|
const serializedTransform = options.transform ? {
|
|
1395
1496
|
pattern: options.transform[0].source,
|
|
1396
1497
|
flags: options.transform[0].flags,
|
|
@@ -1712,14 +1813,17 @@ const warnUnknownKeys = (label, obj, knownKeys, deprecatedKeys) => {
|
|
|
1712
1813
|
};
|
|
1713
1814
|
const KNOWN_SDK_KEYS = /* @__PURE__ */ new Set([
|
|
1714
1815
|
"elementsBaseUrl",
|
|
1816
|
+
"whitelabelDomain",
|
|
1715
1817
|
"apiBaseUrl",
|
|
1716
1818
|
"debug",
|
|
1819
|
+
"allowClipboard",
|
|
1717
1820
|
"measurePerformance",
|
|
1718
1821
|
"timeoutMs",
|
|
1719
1822
|
"retryConfig",
|
|
1720
1823
|
"themeMode",
|
|
1721
1824
|
"theme",
|
|
1722
|
-
"darkTheme"
|
|
1825
|
+
"darkTheme",
|
|
1826
|
+
"sessionAuthorizationUrl"
|
|
1723
1827
|
]);
|
|
1724
1828
|
const DEPRECATED_SDK_KEYS = /* @__PURE__ */ new Map([
|
|
1725
1829
|
["iframeOrigin", 'Use "elementsBaseUrl" instead.']
|
|
@@ -1761,6 +1865,9 @@ const validateSDKConfig = (options = {}) => {
|
|
|
1761
1865
|
if (options.debug !== void 0 && typeof options.debug !== "boolean") {
|
|
1762
1866
|
throw ConfigurationError("debug must be a boolean");
|
|
1763
1867
|
}
|
|
1868
|
+
if (options.allowClipboard !== void 0 && typeof options.allowClipboard !== "boolean") {
|
|
1869
|
+
throw ConfigurationError("allowClipboard must be a boolean");
|
|
1870
|
+
}
|
|
1764
1871
|
if (options.measurePerformance !== void 0 && typeof options.measurePerformance !== "boolean") {
|
|
1765
1872
|
throw ConfigurationError("measurePerformance must be a boolean");
|
|
1766
1873
|
}
|
|
@@ -1787,7 +1894,44 @@ const validateSDKConfig = (options = {}) => {
|
|
|
1787
1894
|
if (!["light", "dark", "auto"].includes(themeMode)) {
|
|
1788
1895
|
throw ConfigurationError('themeMode must be "light", "dark", or "auto"');
|
|
1789
1896
|
}
|
|
1790
|
-
|
|
1897
|
+
if (options.sessionAuthorizationUrl !== void 0) {
|
|
1898
|
+
if (typeof options.sessionAuthorizationUrl !== "string" || options.sessionAuthorizationUrl.trim() === "") {
|
|
1899
|
+
throw ConfigurationError("sessionAuthorizationUrl must be a non-empty string");
|
|
1900
|
+
}
|
|
1901
|
+
try {
|
|
1902
|
+
const parsed = new URL(options.sessionAuthorizationUrl, window.location.origin);
|
|
1903
|
+
if (parsed.protocol === "http:" && parsed.hostname !== "localhost" && parsed.hostname !== "127.0.0.1") {
|
|
1904
|
+
throw ConfigurationError("sessionAuthorizationUrl must use https://.");
|
|
1905
|
+
}
|
|
1906
|
+
} catch (error) {
|
|
1907
|
+
if (error instanceof Error && error.name === "ConfigurationError") {
|
|
1908
|
+
throw error;
|
|
1909
|
+
}
|
|
1910
|
+
}
|
|
1911
|
+
}
|
|
1912
|
+
let resolvedBaseUrl = baseUrl;
|
|
1913
|
+
if (resolvedBaseUrl === void 0 && options.whitelabelDomain !== void 0) {
|
|
1914
|
+
const { whitelabelDomain } = options;
|
|
1915
|
+
if (typeof whitelabelDomain !== "string" || whitelabelDomain.trim().length === 0) {
|
|
1916
|
+
throw ConfigurationError("whitelabelDomain must be a non-empty string");
|
|
1917
|
+
}
|
|
1918
|
+
let domainOrigin;
|
|
1919
|
+
try {
|
|
1920
|
+
const parsed = new URL(whitelabelDomain);
|
|
1921
|
+
if (parsed.protocol !== "https:") {
|
|
1922
|
+
throw ConfigurationError("whitelabelDomain must use https://");
|
|
1923
|
+
}
|
|
1924
|
+
domainOrigin = parsed.origin;
|
|
1925
|
+
} catch (error) {
|
|
1926
|
+
if (error instanceof Error && error.name === "ConfigurationError") {
|
|
1927
|
+
throw error;
|
|
1928
|
+
}
|
|
1929
|
+
throw ConfigurationError("whitelabelDomain must be a valid URL");
|
|
1930
|
+
}
|
|
1931
|
+
const { pathname } = new URL("https://js.basistheory.com/3.0.0-beta.6/elements");
|
|
1932
|
+
resolvedBaseUrl = `${domainOrigin}${pathname}`;
|
|
1933
|
+
}
|
|
1934
|
+
const finalBaseUrl = resolvedBaseUrl || "https://js.basistheory.com/3.0.0-beta.6/elements";
|
|
1791
1935
|
const iframeOrigin = new URL(finalBaseUrl).origin;
|
|
1792
1936
|
return {
|
|
1793
1937
|
iframeOrigin,
|
|
@@ -1795,6 +1939,7 @@ const validateSDKConfig = (options = {}) => {
|
|
|
1795
1939
|
apiBaseUrl: options.apiBaseUrl,
|
|
1796
1940
|
// Optional - auto-detects if not provided
|
|
1797
1941
|
debug: options.debug ?? false,
|
|
1942
|
+
allowClipboard: options.allowClipboard ?? false,
|
|
1798
1943
|
measurePerformance: options.measurePerformance ?? false,
|
|
1799
1944
|
timeoutMs: options.timeoutMs || 3e4,
|
|
1800
1945
|
// 30s default for slow 3G connections
|
|
@@ -1803,7 +1948,9 @@ const validateSDKConfig = (options = {}) => {
|
|
|
1803
1948
|
// Light theme or only theme
|
|
1804
1949
|
darkTheme: options.darkTheme ? mergeWithDefaultTheme(options.darkTheme) : void 0,
|
|
1805
1950
|
// Optional dark theme
|
|
1806
|
-
retryConfig
|
|
1951
|
+
retryConfig,
|
|
1952
|
+
sessionAuthorizationUrl: options.sessionAuthorizationUrl
|
|
1953
|
+
// Optional - required for cardDisplay
|
|
1807
1954
|
};
|
|
1808
1955
|
};
|
|
1809
1956
|
const COMMON_ELEMENT_KEYS = /* @__PURE__ */ new Set([
|
|
@@ -1841,6 +1988,12 @@ const ELEMENT_TYPE_KEYS = {
|
|
|
1841
1988
|
"value",
|
|
1842
1989
|
"text",
|
|
1843
1990
|
"disabled"
|
|
1991
|
+
]),
|
|
1992
|
+
cardDisplay: /* @__PURE__ */ new Set([
|
|
1993
|
+
"tokenId",
|
|
1994
|
+
"number",
|
|
1995
|
+
"cvc",
|
|
1996
|
+
"expiration"
|
|
1844
1997
|
])
|
|
1845
1998
|
};
|
|
1846
1999
|
const validateElementOptions = (type, options = {}) => {
|
|
@@ -1941,7 +2094,109 @@ const BasisTheory = (apiKey, options = {}, queuedCommands) => {
|
|
|
1941
2094
|
let coordinatorClient = null;
|
|
1942
2095
|
let coordinatorReadyPromise = null;
|
|
1943
2096
|
let coordinatorInitStarted = false;
|
|
2097
|
+
let coordinatorLoadTimeout = null;
|
|
2098
|
+
let rejectCoordinatorLoad = null;
|
|
2099
|
+
let destroyed = false;
|
|
2100
|
+
const assertNotDestroyed = () => {
|
|
2101
|
+
if (destroyed) {
|
|
2102
|
+
throw ConfigurationError(
|
|
2103
|
+
"SDK instance has been destroyed. Create a new instance with BasisTheory()"
|
|
2104
|
+
);
|
|
2105
|
+
}
|
|
2106
|
+
};
|
|
2107
|
+
const guardSync = (fn) => (...args) => {
|
|
2108
|
+
assertNotDestroyed();
|
|
2109
|
+
return fn(...args);
|
|
2110
|
+
};
|
|
2111
|
+
const guardAsync = (fn) => async (...args) => {
|
|
2112
|
+
assertNotDestroyed();
|
|
2113
|
+
return fn(...args);
|
|
2114
|
+
};
|
|
1944
2115
|
let currentThemeMode = options.themeMode || "auto";
|
|
2116
|
+
const createLazyElementWrapper = (lazyFactory, elementType, elementId, elementApiKey, elementConfig, elementOptions, ensureCoordinator, notifyUnmount, coordinatorRequest) => {
|
|
2117
|
+
let realElement = null;
|
|
2118
|
+
let loadPromise = null;
|
|
2119
|
+
const loadRealElement = async () => {
|
|
2120
|
+
if (!loadPromise) {
|
|
2121
|
+
loadPromise = (async () => {
|
|
2122
|
+
const factory = await lazyFactory();
|
|
2123
|
+
realElement = factory(
|
|
2124
|
+
elementApiKey,
|
|
2125
|
+
elementConfig,
|
|
2126
|
+
elementOptions,
|
|
2127
|
+
elementId,
|
|
2128
|
+
ensureCoordinator,
|
|
2129
|
+
notifyUnmount,
|
|
2130
|
+
coordinatorRequest
|
|
2131
|
+
);
|
|
2132
|
+
})();
|
|
2133
|
+
}
|
|
2134
|
+
await loadPromise;
|
|
2135
|
+
};
|
|
2136
|
+
const ensureLoaded = () => {
|
|
2137
|
+
if (!realElement) throw ElementError("Element not initialized");
|
|
2138
|
+
return realElement;
|
|
2139
|
+
};
|
|
2140
|
+
const wrapper = {
|
|
2141
|
+
id: elementId,
|
|
2142
|
+
type: elementType,
|
|
2143
|
+
get mounted() {
|
|
2144
|
+
return (realElement == null ? void 0 : realElement.mounted) ?? false;
|
|
2145
|
+
},
|
|
2146
|
+
get loaded() {
|
|
2147
|
+
return (realElement == null ? void 0 : realElement.loaded) ?? false;
|
|
2148
|
+
},
|
|
2149
|
+
mount: async (selector) => {
|
|
2150
|
+
await loadRealElement();
|
|
2151
|
+
return realElement.mount(selector);
|
|
2152
|
+
},
|
|
2153
|
+
unmount: () => ensureLoaded().unmount(),
|
|
2154
|
+
update: async (opts) => ensureLoaded().update(opts),
|
|
2155
|
+
focus: () => ensureLoaded().focus(),
|
|
2156
|
+
blur: () => ensureLoaded().blur(),
|
|
2157
|
+
clear: () => ensureLoaded().clear(),
|
|
2158
|
+
on: (eventType, listener) => {
|
|
2159
|
+
if (!realElement) {
|
|
2160
|
+
let unsubscribe = null;
|
|
2161
|
+
let cancelled = false;
|
|
2162
|
+
loadRealElement().then(() => {
|
|
2163
|
+
if (!cancelled) unsubscribe = realElement.on(eventType, listener);
|
|
2164
|
+
});
|
|
2165
|
+
return () => {
|
|
2166
|
+
cancelled = true;
|
|
2167
|
+
unsubscribe == null ? void 0 : unsubscribe();
|
|
2168
|
+
};
|
|
2169
|
+
}
|
|
2170
|
+
return realElement.on(eventType, listener);
|
|
2171
|
+
},
|
|
2172
|
+
setValueRef: async (refElement) => {
|
|
2173
|
+
if (!realElement) {
|
|
2174
|
+
await loadRealElement();
|
|
2175
|
+
}
|
|
2176
|
+
if (realElement && "setValueRef" in realElement && typeof realElement.setValueRef === "function") {
|
|
2177
|
+
return realElement.setValueRef(refElement);
|
|
2178
|
+
}
|
|
2179
|
+
throw ElementError("setValueRef not available on this element type");
|
|
2180
|
+
}
|
|
2181
|
+
};
|
|
2182
|
+
if (elementType === "card") {
|
|
2183
|
+
Object.defineProperties(wrapper, {
|
|
2184
|
+
number: {
|
|
2185
|
+
get: () => realElement == null ? void 0 : realElement.number,
|
|
2186
|
+
enumerable: true
|
|
2187
|
+
},
|
|
2188
|
+
expiryDate: {
|
|
2189
|
+
get: () => realElement == null ? void 0 : realElement.expiryDate,
|
|
2190
|
+
enumerable: true
|
|
2191
|
+
},
|
|
2192
|
+
cvc: {
|
|
2193
|
+
get: () => realElement == null ? void 0 : realElement.cvc,
|
|
2194
|
+
enumerable: true
|
|
2195
|
+
}
|
|
2196
|
+
});
|
|
2197
|
+
}
|
|
2198
|
+
return wrapper;
|
|
2199
|
+
};
|
|
1945
2200
|
const notifyCoordinatorElementUnmount = async (elementId) => {
|
|
1946
2201
|
if (!coordinatorClient) {
|
|
1947
2202
|
log2("Cannot notify coordinator of unmount - coordinator not initialized", {
|
|
@@ -1961,22 +2216,36 @@ const BasisTheory = (apiKey, options = {}, queuedCommands) => {
|
|
|
1961
2216
|
});
|
|
1962
2217
|
}
|
|
1963
2218
|
};
|
|
2219
|
+
const sendCoordinatorRequest = async (command, payload, options2) => {
|
|
2220
|
+
if (!coordinatorClient) {
|
|
2221
|
+
throw CoordinatorError("Coordinator not initialized");
|
|
2222
|
+
}
|
|
2223
|
+
return coordinatorClient.sendRequest(command, payload, options2);
|
|
2224
|
+
};
|
|
1964
2225
|
let cardElementFactory = null;
|
|
1965
2226
|
let copyButtonElementFactory = null;
|
|
2227
|
+
let cardDisplayElementFactory = null;
|
|
1966
2228
|
const lazyCardElement = async () => {
|
|
1967
2229
|
if (!cardElementFactory) {
|
|
1968
|
-
const module = await import("./create-card-
|
|
2230
|
+
const module = await import("./create-card-C0MwL3Ou.js");
|
|
1969
2231
|
cardElementFactory = module.createCardElement;
|
|
1970
2232
|
}
|
|
1971
2233
|
return cardElementFactory;
|
|
1972
2234
|
};
|
|
1973
2235
|
const lazyCopyButtonElement = async () => {
|
|
1974
2236
|
if (!copyButtonElementFactory) {
|
|
1975
|
-
const module = await import("./create-copy-button-
|
|
2237
|
+
const module = await import("./create-copy-button-DlJ3VvAn.js");
|
|
1976
2238
|
copyButtonElementFactory = module.createCopyButtonElement;
|
|
1977
2239
|
}
|
|
1978
2240
|
return copyButtonElementFactory;
|
|
1979
2241
|
};
|
|
2242
|
+
const lazyCardDisplayElement = async () => {
|
|
2243
|
+
if (!cardDisplayElementFactory) {
|
|
2244
|
+
const module = await import("./create-card-display-DscvxIs4.js");
|
|
2245
|
+
cardDisplayElementFactory = module.createCardDisplayElement;
|
|
2246
|
+
}
|
|
2247
|
+
return cardDisplayElementFactory;
|
|
2248
|
+
};
|
|
1980
2249
|
const syncFactories = {
|
|
1981
2250
|
cardNumber: createCardNumberElement,
|
|
1982
2251
|
cvv: createCVVElement,
|
|
@@ -1985,7 +2254,8 @@ const BasisTheory = (apiKey, options = {}, queuedCommands) => {
|
|
|
1985
2254
|
};
|
|
1986
2255
|
const lazyFactories = {
|
|
1987
2256
|
card: lazyCardElement,
|
|
1988
|
-
copyButton: lazyCopyButtonElement
|
|
2257
|
+
copyButton: lazyCopyButtonElement,
|
|
2258
|
+
cardDisplay: lazyCardDisplayElement
|
|
1989
2259
|
};
|
|
1990
2260
|
const ensureCoordinatorInitialized = () => {
|
|
1991
2261
|
if (coordinatorReadyPromise) {
|
|
@@ -2027,7 +2297,10 @@ const BasisTheory = (apiKey, options = {}, queuedCommands) => {
|
|
|
2027
2297
|
url: coordinatorIframe.src
|
|
2028
2298
|
});
|
|
2029
2299
|
await new Promise((resolve, reject) => {
|
|
2030
|
-
|
|
2300
|
+
rejectCoordinatorLoad = reject;
|
|
2301
|
+
coordinatorLoadTimeout = setTimeout(() => {
|
|
2302
|
+
coordinatorLoadTimeout = null;
|
|
2303
|
+
rejectCoordinatorLoad = null;
|
|
2031
2304
|
reject(
|
|
2032
2305
|
new Error(
|
|
2033
2306
|
`Coordinator load timeout (${config.timeoutMs}ms). Try increasing timeoutMs for slow connections.`
|
|
@@ -2037,13 +2310,21 @@ const BasisTheory = (apiKey, options = {}, queuedCommands) => {
|
|
|
2037
2310
|
coordinatorIframe.addEventListener(
|
|
2038
2311
|
"load",
|
|
2039
2312
|
() => {
|
|
2040
|
-
|
|
2313
|
+
if (coordinatorLoadTimeout !== null) {
|
|
2314
|
+
clearTimeout(coordinatorLoadTimeout);
|
|
2315
|
+
}
|
|
2316
|
+
coordinatorLoadTimeout = null;
|
|
2317
|
+
rejectCoordinatorLoad = null;
|
|
2041
2318
|
log2("Coordinator iframe loaded");
|
|
2042
2319
|
resolve();
|
|
2043
2320
|
},
|
|
2044
2321
|
{ once: true }
|
|
2045
2322
|
);
|
|
2046
2323
|
});
|
|
2324
|
+
if (destroyed) {
|
|
2325
|
+
log2("Coordinator load resolved after destroy — aborting init");
|
|
2326
|
+
return;
|
|
2327
|
+
}
|
|
2047
2328
|
coordinatorClient = createPostMessageClient(coordinatorIframe, {
|
|
2048
2329
|
targetOrigin: new URL(config.elementsBaseUrl).origin,
|
|
2049
2330
|
timeout: 3e4,
|
|
@@ -2057,10 +2338,16 @@ const BasisTheory = (apiKey, options = {}, queuedCommands) => {
|
|
|
2057
2338
|
// Optional - auto-detects if not provided
|
|
2058
2339
|
apiTimeout: 3e4,
|
|
2059
2340
|
apiRetries: 3,
|
|
2341
|
+
// Frozen by the coordinator on this first config; copy references are
|
|
2342
|
+
// refused unless it's enabled here.
|
|
2343
|
+
allowClipboard: config.allowClipboard,
|
|
2060
2344
|
debug: config.debug || false,
|
|
2061
2345
|
theme: config.theme,
|
|
2062
2346
|
darkTheme: config.darkTheme,
|
|
2063
2347
|
themeMode: config.themeMode
|
|
2348
|
+
// sessionAuthorizationUrl is intentionally NOT sent to the coordinator:
|
|
2349
|
+
// the merchant-authorization fetch now runs in the parent page (see
|
|
2350
|
+
// create-card-display.ts), so the coordinator never needs the URL.
|
|
2064
2351
|
});
|
|
2065
2352
|
log2("Coordinator initialized successfully");
|
|
2066
2353
|
};
|
|
@@ -2070,7 +2357,7 @@ const BasisTheory = (apiKey, options = {}, queuedCommands) => {
|
|
|
2070
2357
|
* createElement is now SYNCHRONOUS - returns Element instantly
|
|
2071
2358
|
* Coordinator initialization starts on first element (but doesn't block)
|
|
2072
2359
|
*/
|
|
2073
|
-
createElement: (type, elementOptions) => {
|
|
2360
|
+
createElement: guardSync((type, elementOptions) => {
|
|
2074
2361
|
const syncFactory = syncFactories[type];
|
|
2075
2362
|
const lazyFactory = lazyFactories[type];
|
|
2076
2363
|
if (!syncFactory && !lazyFactory) {
|
|
@@ -2079,6 +2366,12 @@ const BasisTheory = (apiKey, options = {}, queuedCommands) => {
|
|
|
2079
2366
|
if (elementOptions) {
|
|
2080
2367
|
validateElementOptions(type, elementOptions);
|
|
2081
2368
|
}
|
|
2369
|
+
if (type === "copyButton" && !config.allowClipboard) {
|
|
2370
|
+
throw ConfigurationError(
|
|
2371
|
+
"copyButton requires allowClipboard: true on BasisTheory() initialization. Clipboard access for raw card data may not be PCI compliant and must be enabled explicitly.",
|
|
2372
|
+
{ received: config.allowClipboard, expected: true, elementType: type }
|
|
2373
|
+
);
|
|
2374
|
+
}
|
|
2082
2375
|
const localElementId = `${type}-${Date.now()}-${Math.random().toString(36).slice(2, 9)}`;
|
|
2083
2376
|
log2("Creating element (sync)", {
|
|
2084
2377
|
type,
|
|
@@ -2094,79 +2387,21 @@ const BasisTheory = (apiKey, options = {}, queuedCommands) => {
|
|
|
2094
2387
|
elementOptions,
|
|
2095
2388
|
localElementId,
|
|
2096
2389
|
ensureCoordinatorInitialized,
|
|
2097
|
-
notifyCoordinatorElementUnmount
|
|
2390
|
+
notifyCoordinatorElementUnmount,
|
|
2391
|
+
sendCoordinatorRequest
|
|
2098
2392
|
);
|
|
2099
2393
|
} else {
|
|
2100
|
-
|
|
2101
|
-
|
|
2102
|
-
const loadRealElement = async () => {
|
|
2103
|
-
if (!loadPromise) {
|
|
2104
|
-
loadPromise = (async () => {
|
|
2105
|
-
const factory = await lazyFactory();
|
|
2106
|
-
realElement = factory(
|
|
2107
|
-
apiKey,
|
|
2108
|
-
config,
|
|
2109
|
-
elementOptions,
|
|
2110
|
-
localElementId,
|
|
2111
|
-
ensureCoordinatorInitialized,
|
|
2112
|
-
notifyCoordinatorElementUnmount
|
|
2113
|
-
);
|
|
2114
|
-
})();
|
|
2115
|
-
}
|
|
2116
|
-
await loadPromise;
|
|
2117
|
-
};
|
|
2118
|
-
element = {
|
|
2119
|
-
id: localElementId,
|
|
2394
|
+
element = createLazyElementWrapper(
|
|
2395
|
+
lazyFactory,
|
|
2120
2396
|
type,
|
|
2121
|
-
|
|
2122
|
-
|
|
2123
|
-
|
|
2124
|
-
|
|
2125
|
-
|
|
2126
|
-
|
|
2127
|
-
|
|
2128
|
-
|
|
2129
|
-
return realElement.mount(selector);
|
|
2130
|
-
},
|
|
2131
|
-
unmount: () => {
|
|
2132
|
-
if (!realElement) throw ElementError("Element not initialized");
|
|
2133
|
-
return realElement.unmount();
|
|
2134
|
-
},
|
|
2135
|
-
update: async (opts) => {
|
|
2136
|
-
if (!realElement) throw ElementError("Element not initialized");
|
|
2137
|
-
return realElement.update(opts);
|
|
2138
|
-
},
|
|
2139
|
-
focus: () => {
|
|
2140
|
-
if (!realElement) throw ElementError("Element not initialized");
|
|
2141
|
-
return realElement.focus();
|
|
2142
|
-
},
|
|
2143
|
-
blur: () => {
|
|
2144
|
-
if (!realElement) throw ElementError("Element not initialized");
|
|
2145
|
-
return realElement.blur();
|
|
2146
|
-
},
|
|
2147
|
-
clear: () => {
|
|
2148
|
-
if (!realElement) throw ElementError("Element not initialized");
|
|
2149
|
-
return realElement.clear();
|
|
2150
|
-
},
|
|
2151
|
-
on: (eventType, listener) => {
|
|
2152
|
-
if (!realElement) {
|
|
2153
|
-
loadRealElement().then(() => realElement.on(eventType, listener));
|
|
2154
|
-
return () => {
|
|
2155
|
-
};
|
|
2156
|
-
}
|
|
2157
|
-
return realElement.on(eventType, listener);
|
|
2158
|
-
},
|
|
2159
|
-
// Forward setValueRef for CopyButtonElement
|
|
2160
|
-
setValueRef: async (refElement) => {
|
|
2161
|
-
if (!realElement) {
|
|
2162
|
-
await loadRealElement();
|
|
2163
|
-
}
|
|
2164
|
-
if (realElement && "setValueRef" in realElement && typeof realElement.setValueRef === "function") {
|
|
2165
|
-
return realElement.setValueRef(refElement);
|
|
2166
|
-
}
|
|
2167
|
-
throw ElementError("setValueRef not available on this element type");
|
|
2168
|
-
}
|
|
2169
|
-
};
|
|
2397
|
+
localElementId,
|
|
2398
|
+
apiKey,
|
|
2399
|
+
config,
|
|
2400
|
+
elementOptions,
|
|
2401
|
+
ensureCoordinatorInitialized,
|
|
2402
|
+
notifyCoordinatorElementUnmount,
|
|
2403
|
+
sendCoordinatorRequest
|
|
2404
|
+
);
|
|
2170
2405
|
}
|
|
2171
2406
|
elements.set(element.id, element);
|
|
2172
2407
|
if (type === "cardNumber") {
|
|
@@ -2205,8 +2440,8 @@ const BasisTheory = (apiKey, options = {}, queuedCommands) => {
|
|
|
2205
2440
|
});
|
|
2206
2441
|
}
|
|
2207
2442
|
return element;
|
|
2208
|
-
},
|
|
2209
|
-
tokenize: async (payload, options2) => {
|
|
2443
|
+
}),
|
|
2444
|
+
tokenize: guardAsync(async (payload, options2) => {
|
|
2210
2445
|
log2("tokenize called", {
|
|
2211
2446
|
hasPayload: !!payload,
|
|
2212
2447
|
hasOptions: !!options2,
|
|
@@ -2243,7 +2478,7 @@ const BasisTheory = (apiKey, options = {}, queuedCommands) => {
|
|
|
2243
2478
|
});
|
|
2244
2479
|
throw error;
|
|
2245
2480
|
}
|
|
2246
|
-
},
|
|
2481
|
+
}),
|
|
2247
2482
|
/**
|
|
2248
2483
|
* Token CRUD operations
|
|
2249
2484
|
* Supports Element references - automatically resolves to secure values
|
|
@@ -2253,7 +2488,7 @@ const BasisTheory = (apiKey, options = {}, queuedCommands) => {
|
|
|
2253
2488
|
* Create a new token
|
|
2254
2489
|
* Supports Element references in data (same as tokenize)
|
|
2255
2490
|
*/
|
|
2256
|
-
create: async (request) => {
|
|
2491
|
+
create: guardAsync(async (request) => {
|
|
2257
2492
|
if (!request || typeof request !== "object" || Array.isArray(request)) {
|
|
2258
2493
|
throw ValidationError("Token data must be a non-null object");
|
|
2259
2494
|
}
|
|
@@ -2288,7 +2523,7 @@ const BasisTheory = (apiKey, options = {}, queuedCommands) => {
|
|
|
2288
2523
|
});
|
|
2289
2524
|
throw error;
|
|
2290
2525
|
}
|
|
2291
|
-
},
|
|
2526
|
+
}),
|
|
2292
2527
|
/**
|
|
2293
2528
|
* Retrieve a token by ID
|
|
2294
2529
|
*
|
|
@@ -2296,7 +2531,7 @@ const BasisTheory = (apiKey, options = {}, queuedCommands) => {
|
|
|
2296
2531
|
* @param options - Optional configuration
|
|
2297
2532
|
* @param options.apiKey - Optional session key for authorized access (from sessions.create + authorize)
|
|
2298
2533
|
*/
|
|
2299
|
-
retrieve: async (id, options2) => {
|
|
2534
|
+
retrieve: guardAsync(async (id, options2) => {
|
|
2300
2535
|
log2("tokens.retrieve called", {
|
|
2301
2536
|
tokenId: id,
|
|
2302
2537
|
hasSessionKey: !!(options2 == null ? void 0 : options2.apiKey)
|
|
@@ -2326,12 +2561,12 @@ const BasisTheory = (apiKey, options = {}, queuedCommands) => {
|
|
|
2326
2561
|
});
|
|
2327
2562
|
throw error;
|
|
2328
2563
|
}
|
|
2329
|
-
},
|
|
2564
|
+
}),
|
|
2330
2565
|
/**
|
|
2331
2566
|
* Update a token
|
|
2332
2567
|
* Supports Element references in data
|
|
2333
2568
|
*/
|
|
2334
|
-
update: async (id, request) => {
|
|
2569
|
+
update: guardAsync(async (id, request) => {
|
|
2335
2570
|
log2("tokens.update called", { tokenId: id });
|
|
2336
2571
|
if (!coordinatorClient) {
|
|
2337
2572
|
await initializeCoordinator();
|
|
@@ -2353,7 +2588,7 @@ const BasisTheory = (apiKey, options = {}, queuedCommands) => {
|
|
|
2353
2588
|
});
|
|
2354
2589
|
throw error;
|
|
2355
2590
|
}
|
|
2356
|
-
},
|
|
2591
|
+
}),
|
|
2357
2592
|
/**
|
|
2358
2593
|
* Encrypt token data with client-side JWE
|
|
2359
2594
|
* Uses ECDH-ES key agreement and A256GCM authenticated encryption
|
|
@@ -2364,7 +2599,7 @@ const BasisTheory = (apiKey, options = {}, queuedCommands) => {
|
|
|
2364
2599
|
* @param keyId - Key identifier for decryption lookup
|
|
2365
2600
|
* @returns Encrypted JWE token(s)
|
|
2366
2601
|
*/
|
|
2367
|
-
encrypt: async (tokenData, publicKeyPEM, keyId) => {
|
|
2602
|
+
encrypt: guardAsync(async (tokenData, publicKeyPEM, keyId) => {
|
|
2368
2603
|
log2("tokens.encrypt called", {
|
|
2369
2604
|
isSingleToken: "type" in tokenData && "data" in tokenData,
|
|
2370
2605
|
keyId
|
|
@@ -2405,14 +2640,14 @@ const BasisTheory = (apiKey, options = {}, queuedCommands) => {
|
|
|
2405
2640
|
});
|
|
2406
2641
|
throw error;
|
|
2407
2642
|
}
|
|
2408
|
-
}
|
|
2643
|
+
})
|
|
2409
2644
|
},
|
|
2410
2645
|
sessions: {
|
|
2411
2646
|
/**
|
|
2412
2647
|
* Create a new session for temporary elevated access
|
|
2413
2648
|
* Note: Session must be authorized by a Private Application on your backend
|
|
2414
2649
|
*/
|
|
2415
|
-
create: async () => {
|
|
2650
|
+
create: guardAsync(async () => {
|
|
2416
2651
|
log2("sessions.create called");
|
|
2417
2652
|
if (!coordinatorClient) {
|
|
2418
2653
|
await initializeCoordinator();
|
|
@@ -2436,13 +2671,13 @@ const BasisTheory = (apiKey, options = {}, queuedCommands) => {
|
|
|
2436
2671
|
});
|
|
2437
2672
|
throw error;
|
|
2438
2673
|
}
|
|
2439
|
-
}
|
|
2674
|
+
})
|
|
2440
2675
|
},
|
|
2441
2676
|
tokenIntents: {
|
|
2442
2677
|
/**
|
|
2443
2678
|
* Create a token intent with element reference support
|
|
2444
2679
|
*/
|
|
2445
|
-
create: async (data, options2) => {
|
|
2680
|
+
create: guardAsync(async (data, options2) => {
|
|
2446
2681
|
log2("tokenIntents.create called", {
|
|
2447
2682
|
type: data.type,
|
|
2448
2683
|
hasData: !!data.data,
|
|
@@ -2475,11 +2710,11 @@ const BasisTheory = (apiKey, options = {}, queuedCommands) => {
|
|
|
2475
2710
|
});
|
|
2476
2711
|
throw error;
|
|
2477
2712
|
}
|
|
2478
|
-
},
|
|
2713
|
+
}),
|
|
2479
2714
|
/**
|
|
2480
2715
|
* Get a token intent by ID
|
|
2481
2716
|
*/
|
|
2482
|
-
get: async (id, options2) => {
|
|
2717
|
+
get: guardAsync(async (id, options2) => {
|
|
2483
2718
|
log2("tokenIntents.get called", {
|
|
2484
2719
|
intentId: id
|
|
2485
2720
|
});
|
|
@@ -2507,15 +2742,16 @@ const BasisTheory = (apiKey, options = {}, queuedCommands) => {
|
|
|
2507
2742
|
});
|
|
2508
2743
|
throw error;
|
|
2509
2744
|
}
|
|
2510
|
-
}
|
|
2745
|
+
})
|
|
2511
2746
|
},
|
|
2512
2747
|
proxy: (() => {
|
|
2513
|
-
const invokeProxy = async (method, options2 = {}) => {
|
|
2748
|
+
const invokeProxy = guardAsync(async (method, options2 = {}) => {
|
|
2514
2749
|
validateProxyOptions({ ...options2, method });
|
|
2515
2750
|
log2("proxy invoked", {
|
|
2516
2751
|
method,
|
|
2517
2752
|
hasUrl: !!options2.url,
|
|
2518
|
-
hasProxyKey: !!options2.proxyKey
|
|
2753
|
+
hasProxyKey: !!options2.proxyKey,
|
|
2754
|
+
hasApiKey: !!options2.apiKey
|
|
2519
2755
|
});
|
|
2520
2756
|
if (!coordinatorClient) {
|
|
2521
2757
|
log2("Waiting for coordinator initialization");
|
|
@@ -2534,7 +2770,8 @@ const BasisTheory = (apiKey, options = {}, queuedCommands) => {
|
|
|
2534
2770
|
proxyKey: options2.proxyKey,
|
|
2535
2771
|
headers: options2.headers,
|
|
2536
2772
|
body: resolvedBody,
|
|
2537
|
-
includeResponseHeaders: options2.includeResponseHeaders
|
|
2773
|
+
includeResponseHeaders: options2.includeResponseHeaders,
|
|
2774
|
+
apiKey: options2.apiKey
|
|
2538
2775
|
},
|
|
2539
2776
|
{ retries: 0 }
|
|
2540
2777
|
);
|
|
@@ -2547,7 +2784,7 @@ const BasisTheory = (apiKey, options = {}, queuedCommands) => {
|
|
|
2547
2784
|
});
|
|
2548
2785
|
throw error;
|
|
2549
2786
|
}
|
|
2550
|
-
};
|
|
2787
|
+
});
|
|
2551
2788
|
const proxyVerb = (method) => (options2) => invokeProxy(method, options2 ?? {});
|
|
2552
2789
|
return {
|
|
2553
2790
|
get: proxyVerb("GET"),
|
|
@@ -2557,7 +2794,7 @@ const BasisTheory = (apiKey, options = {}, queuedCommands) => {
|
|
|
2557
2794
|
delete: proxyVerb("DELETE")
|
|
2558
2795
|
};
|
|
2559
2796
|
})(),
|
|
2560
|
-
updateThemeMode: async (mode) => {
|
|
2797
|
+
updateThemeMode: guardAsync(async (mode) => {
|
|
2561
2798
|
log2("updateThemeMode called", {
|
|
2562
2799
|
oldMode: currentThemeMode,
|
|
2563
2800
|
newMode: mode,
|
|
@@ -2596,6 +2833,79 @@ const BasisTheory = (apiKey, options = {}, queuedCommands) => {
|
|
|
2596
2833
|
mode,
|
|
2597
2834
|
updatedCount: Array.from(elements.values()).filter((el) => el.mounted).length
|
|
2598
2835
|
});
|
|
2836
|
+
}),
|
|
2837
|
+
/**
|
|
2838
|
+
* Destroys this instance and removes its elements from the page. Once
|
|
2839
|
+
* destroyed, its other methods throw; create a new instance with
|
|
2840
|
+
* BasisTheory() to recover. Safe to call more than once.
|
|
2841
|
+
*/
|
|
2842
|
+
destroy: async () => {
|
|
2843
|
+
if (destroyed) {
|
|
2844
|
+
return;
|
|
2845
|
+
}
|
|
2846
|
+
destroyed = true;
|
|
2847
|
+
log2("Destroying SDK instance", {
|
|
2848
|
+
elementCount: elements.size,
|
|
2849
|
+
hasCoordinator: coordinatorIframe !== null
|
|
2850
|
+
});
|
|
2851
|
+
for (const [id, element] of elements) {
|
|
2852
|
+
if (!element.mounted) {
|
|
2853
|
+
continue;
|
|
2854
|
+
}
|
|
2855
|
+
try {
|
|
2856
|
+
element.unmount();
|
|
2857
|
+
} catch (error) {
|
|
2858
|
+
log2("Failed to unmount element during destroy", {
|
|
2859
|
+
elementId: id,
|
|
2860
|
+
error: error.message
|
|
2861
|
+
});
|
|
2862
|
+
}
|
|
2863
|
+
}
|
|
2864
|
+
elements.clear();
|
|
2865
|
+
if (coordinatorLoadTimeout !== null) {
|
|
2866
|
+
clearTimeout(coordinatorLoadTimeout);
|
|
2867
|
+
coordinatorLoadTimeout = null;
|
|
2868
|
+
}
|
|
2869
|
+
if (rejectCoordinatorLoad) {
|
|
2870
|
+
rejectCoordinatorLoad(
|
|
2871
|
+
ConfigurationError(
|
|
2872
|
+
"SDK instance has been destroyed. Create a new instance with BasisTheory()"
|
|
2873
|
+
)
|
|
2874
|
+
);
|
|
2875
|
+
rejectCoordinatorLoad = null;
|
|
2876
|
+
}
|
|
2877
|
+
if (coordinatorClient) {
|
|
2878
|
+
const CACHE_CLEAR_TIMEOUT_MS = 2e3;
|
|
2879
|
+
const cacheCleared = coordinatorClient.sendRequest("CMD_CLEAR_ALL_CACHE", {}, { retries: 0 }).catch((error) => {
|
|
2880
|
+
log2("Failed to clear coordinator cache during destroy", {
|
|
2881
|
+
error: error.message
|
|
2882
|
+
});
|
|
2883
|
+
});
|
|
2884
|
+
let capTimeout;
|
|
2885
|
+
const cap = new Promise((resolve) => {
|
|
2886
|
+
capTimeout = setTimeout(() => {
|
|
2887
|
+
log2("Coordinator cache-clear timed out during destroy", {
|
|
2888
|
+
timeoutMs: CACHE_CLEAR_TIMEOUT_MS
|
|
2889
|
+
});
|
|
2890
|
+
resolve();
|
|
2891
|
+
}, CACHE_CLEAR_TIMEOUT_MS);
|
|
2892
|
+
});
|
|
2893
|
+
await Promise.race([cacheCleared, cap]);
|
|
2894
|
+
if (capTimeout !== void 0) {
|
|
2895
|
+
clearTimeout(capTimeout);
|
|
2896
|
+
}
|
|
2897
|
+
}
|
|
2898
|
+
if (coordinatorClient) {
|
|
2899
|
+
coordinatorClient.destroy();
|
|
2900
|
+
coordinatorClient = null;
|
|
2901
|
+
}
|
|
2902
|
+
if (coordinatorIframe) {
|
|
2903
|
+
coordinatorIframe.remove();
|
|
2904
|
+
coordinatorIframe = null;
|
|
2905
|
+
}
|
|
2906
|
+
coordinatorReadyPromise = null;
|
|
2907
|
+
coordinatorInitStarted = false;
|
|
2908
|
+
log2("SDK instance destroyed");
|
|
2599
2909
|
}
|
|
2600
2910
|
};
|
|
2601
2911
|
if (queuedCommands && queuedCommands.length > 0) {
|
|
@@ -2650,8 +2960,8 @@ const BasisTheory = (apiKey, options = {}, queuedCommands) => {
|
|
|
2650
2960
|
if (typeof window !== "undefined" && typeof document !== "undefined" && document.currentScript && !window.BasisTheory) {
|
|
2651
2961
|
window.BasisTheory = BasisTheory;
|
|
2652
2962
|
}
|
|
2653
|
-
const version = "3.0.0-beta.
|
|
2654
|
-
const buildDate = "2026-
|
|
2963
|
+
const version = "3.0.0-beta.6";
|
|
2964
|
+
const buildDate = "2026-08-05T15:06:02.574Z";
|
|
2655
2965
|
if (typeof window !== "undefined") {
|
|
2656
2966
|
window.__BasisTheorySDK__ = BasisTheory;
|
|
2657
2967
|
}
|
|
@@ -2660,10 +2970,11 @@ export {
|
|
|
2660
2970
|
ConfigurationError as C,
|
|
2661
2971
|
ElementError as E,
|
|
2662
2972
|
createPostMessageClient as a,
|
|
2663
|
-
|
|
2973
|
+
bindCoordinatorPort as b,
|
|
2664
2974
|
createIframe as c,
|
|
2665
|
-
|
|
2666
|
-
|
|
2975
|
+
createEventDispatcher as d,
|
|
2976
|
+
createMounter as e,
|
|
2977
|
+
buildDate as f,
|
|
2667
2978
|
log as l,
|
|
2668
2979
|
version as v
|
|
2669
2980
|
};
|