@basis-theory/web-elements 3.0.0 → 3.1.0
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 +49 -0
- package/dist/basis-theory-sdk.es.js +1 -1
- package/dist/basis-theory-sdk.umd.js +1 -1
- package/dist/basis-theory-sdk.umd.js.map +1 -1
- package/dist/{create-card-C94szxMV.js → create-card-CoTyU6ju.js} +10 -1
- package/dist/create-card-CoTyU6ju.js.map +1 -0
- package/dist/{create-card-display-DsLzA_vl.js → create-card-display-DQmTA_8S.js} +3 -1
- package/dist/{create-card-display-DsLzA_vl.js.map → create-card-display-DQmTA_8S.js.map} +1 -1
- package/dist/{create-copy-button-Z1s9ao67.js → create-copy-button-D8VeinHW.js} +3 -1
- package/dist/create-copy-button-D8VeinHW.js.map +1 -0
- package/dist/{index-DIVQdm8b.js → index-hHam_H0I.js} +214 -11
- package/dist/index-hHam_H0I.js.map +1 -0
- package/dist/index.d.ts +135 -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 +5 -5
- package/dist/create-card-C94szxMV.js.map +0 -1
- package/dist/create-copy-button-Z1s9ao67.js.map +0 -1
- package/dist/index-DIVQdm8b.js.map +0 -1
|
@@ -150,6 +150,8 @@ const generateId = () => {
|
|
|
150
150
|
const randomPart = (random() + random() + random() + random()).substring(0, 32);
|
|
151
151
|
return `${randomPart.substring(0, 8)}-${randomPart.substring(8, 12)}-${randomPart.substring(12, 16)}-${randomPart.substring(16, 20)}-${randomPart.substring(20, 32)}`;
|
|
152
152
|
};
|
|
153
|
+
const LANGUAGE_TAG = /^[a-zA-Z]{2,3}(-[a-zA-Z0-9]{1,8})*$/;
|
|
154
|
+
const isLanguageTag = (value) => typeof value === "string" && LANGUAGE_TAG.test(value);
|
|
153
155
|
const log = (action, metadata) => {
|
|
154
156
|
};
|
|
155
157
|
const createBasisTheoryError = (code, message, details) => {
|
|
@@ -195,6 +197,16 @@ const ConfigurationError = (message, details) => {
|
|
|
195
197
|
error.name = "ConfigurationError";
|
|
196
198
|
return error;
|
|
197
199
|
};
|
|
200
|
+
const HttpClientError = (message, status, data, headers) => {
|
|
201
|
+
const error = createBasisTheoryError("HTTP_CLIENT_ERROR", message, {
|
|
202
|
+
status
|
|
203
|
+
});
|
|
204
|
+
error.name = "HttpClientError";
|
|
205
|
+
error.status = status;
|
|
206
|
+
error.data = data;
|
|
207
|
+
error.headers = headers;
|
|
208
|
+
return error;
|
|
209
|
+
};
|
|
198
210
|
const ALLOWED_PROXY_SCHEMES = /* @__PURE__ */ new Set(["https:"]);
|
|
199
211
|
const ALLOWED_METHODS = /* @__PURE__ */ new Set([
|
|
200
212
|
"GET",
|
|
@@ -381,6 +393,35 @@ const validateProxyTarget = (url, proxyKey) => {
|
|
|
381
393
|
validateProxyUrl(url);
|
|
382
394
|
}
|
|
383
395
|
};
|
|
396
|
+
const FORBIDDEN_DESTINATION_HEADERS = new Set([...FORBIDDEN_PROXY_HEADERS].filter((header) => header !== "content-type"));
|
|
397
|
+
const validateDestinationHeaders = (headers) => {
|
|
398
|
+
if (!headers)
|
|
399
|
+
return;
|
|
400
|
+
for (const [key, value] of Object.entries(headers)) {
|
|
401
|
+
if (/[\r\n]/.test(value)) {
|
|
402
|
+
throw ValidationError(`Header '${key}' value contains illegal CRLF`, "headers");
|
|
403
|
+
}
|
|
404
|
+
if (/[\r\n]/.test(key)) {
|
|
405
|
+
throw ValidationError(`Header name '${key}' contains illegal CRLF`, "headers");
|
|
406
|
+
}
|
|
407
|
+
if (FORBIDDEN_DESTINATION_HEADERS.has(key.toLowerCase().trim())) {
|
|
408
|
+
throw ValidationError(`Header '${key}' is not allowed in HTTP client requests`, "headers");
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
};
|
|
412
|
+
const validateDestinationRequest = (options) => {
|
|
413
|
+
if (options !== void 0 && (typeof options !== "object" || options === null)) {
|
|
414
|
+
throw ValidationError("HTTP client options must be a plain object", "options");
|
|
415
|
+
}
|
|
416
|
+
if ((options == null ? void 0 : options.method) !== void 0 && !ALLOWED_METHODS.has(options.method)) {
|
|
417
|
+
throw ValidationError(`Method '${options.method}' is not allowed`, "method");
|
|
418
|
+
}
|
|
419
|
+
if (typeof (options == null ? void 0 : options.url) !== "string" || options.url.length === 0) {
|
|
420
|
+
throw ValidationError("url is required", "url");
|
|
421
|
+
}
|
|
422
|
+
validateProxyUrl(options.url);
|
|
423
|
+
validateDestinationHeaders(options == null ? void 0 : options.headers);
|
|
424
|
+
};
|
|
384
425
|
const validateProxyOptions = (options) => {
|
|
385
426
|
if (options !== void 0 && (typeof options !== "object" || options === null)) {
|
|
386
427
|
throw ValidationError("Proxy options must be a plain object", "options");
|
|
@@ -450,6 +491,8 @@ const createPostMessageClient = (iframe, config) => {
|
|
|
450
491
|
...error.retryCount !== void 0 && {
|
|
451
492
|
retryCount: error.retryCount
|
|
452
493
|
},
|
|
494
|
+
...error.data !== void 0 && { data: error.data },
|
|
495
|
+
...error.headers && { headers: error.headers },
|
|
453
496
|
...error.details && { details: error.details }
|
|
454
497
|
});
|
|
455
498
|
pending.reject(reconstructedError);
|
|
@@ -878,17 +921,21 @@ const createCardNumberElement = (apiKey, sdkConfig, options = {}, coordinatorEle
|
|
|
878
921
|
elementId: id,
|
|
879
922
|
// Include element ID for validation
|
|
880
923
|
apiKey,
|
|
924
|
+
environment: sdkConfig.environment,
|
|
881
925
|
apiTimeout: sdkConfig.timeoutMs,
|
|
882
926
|
apiRetries: sdkConfig.retryConfig.maxRetries,
|
|
883
927
|
theme: sdkConfig.theme,
|
|
884
928
|
darkTheme: sdkConfig.darkTheme,
|
|
885
929
|
themeMode: sdkConfig.themeMode,
|
|
930
|
+
direction: sdkConfig.direction,
|
|
931
|
+
language: sdkConfig.language,
|
|
886
932
|
placeholder: options.placeholder,
|
|
887
933
|
disabled: options.disabled,
|
|
888
934
|
readOnly: options.readOnly,
|
|
889
935
|
debug: sdkConfig.debug,
|
|
890
936
|
binLookup: options.binLookup,
|
|
891
|
-
coBadge: options.coBadge
|
|
937
|
+
coBadge: options.coBadge,
|
|
938
|
+
enterKeyHint: options.enterKeyHint
|
|
892
939
|
});
|
|
893
940
|
if (iframe) iframe.style.opacity = "1";
|
|
894
941
|
} catch (error) {
|
|
@@ -959,6 +1006,9 @@ const createCardNumberElement = (apiKey, sdkConfig, options = {}, coordinatorEle
|
|
|
959
1006
|
if (newOptions.coBadge !== void 0) {
|
|
960
1007
|
updatePayload.coBadge = newOptions.coBadge;
|
|
961
1008
|
}
|
|
1009
|
+
if ("enterKeyHint" in newOptions) {
|
|
1010
|
+
updatePayload.enterKeyHint = newOptions.enterKeyHint;
|
|
1011
|
+
}
|
|
962
1012
|
if (newOptions.themeMode !== void 0) {
|
|
963
1013
|
updatePayload.themeMode = newOptions.themeMode;
|
|
964
1014
|
updatePayload.theme = sdkConfig.theme;
|
|
@@ -1097,13 +1147,17 @@ const createCVVElement = (apiKey, sdkConfig, options = {}, coordinatorElementId,
|
|
|
1097
1147
|
theme: sdkConfig.theme,
|
|
1098
1148
|
darkTheme: sdkConfig.darkTheme,
|
|
1099
1149
|
themeMode: sdkConfig.themeMode,
|
|
1150
|
+
direction: sdkConfig.direction,
|
|
1151
|
+
language: sdkConfig.language,
|
|
1100
1152
|
apiKey,
|
|
1153
|
+
environment: sdkConfig.environment,
|
|
1101
1154
|
apiTimeout: sdkConfig.timeoutMs,
|
|
1102
1155
|
apiRetries: sdkConfig.retryConfig.maxRetries,
|
|
1103
1156
|
placeholder: options.placeholder,
|
|
1104
1157
|
disabled: options.disabled,
|
|
1105
1158
|
readOnly: options.readOnly,
|
|
1106
1159
|
showToggle: options.showToggle,
|
|
1160
|
+
enterKeyHint: options.enterKeyHint,
|
|
1107
1161
|
debug: sdkConfig.debug
|
|
1108
1162
|
});
|
|
1109
1163
|
if (iframe) iframe.style.opacity = "1";
|
|
@@ -1160,6 +1214,11 @@ const createCVVElement = (apiKey, sdkConfig, options = {}, coordinatorElementId,
|
|
|
1160
1214
|
placeholder: newOptions.placeholder,
|
|
1161
1215
|
disabled: newOptions.disabled,
|
|
1162
1216
|
readOnly: newOptions.readOnly,
|
|
1217
|
+
// Forwarded only when the caller named it, so an explicit
|
|
1218
|
+
// `enterKeyHint: undefined` clears the hint but a partial update keeps it
|
|
1219
|
+
..."enterKeyHint" in newOptions && {
|
|
1220
|
+
enterKeyHint: newOptions.enterKeyHint
|
|
1221
|
+
},
|
|
1163
1222
|
// ✅ SDK auto-coordination: Pass brand info for dynamic maxlength
|
|
1164
1223
|
cardBrand: newOptions.cardBrand,
|
|
1165
1224
|
cvvLengths: newOptions.cvvLengths
|
|
@@ -1296,12 +1355,16 @@ const createExpiryElement = (apiKey, sdkConfig, options = {}, coordinatorElement
|
|
|
1296
1355
|
theme: sdkConfig.theme,
|
|
1297
1356
|
darkTheme: sdkConfig.darkTheme,
|
|
1298
1357
|
themeMode: sdkConfig.themeMode,
|
|
1358
|
+
direction: sdkConfig.direction,
|
|
1359
|
+
language: sdkConfig.language,
|
|
1299
1360
|
apiKey,
|
|
1361
|
+
environment: sdkConfig.environment,
|
|
1300
1362
|
apiTimeout: sdkConfig.timeoutMs,
|
|
1301
1363
|
apiRetries: sdkConfig.retryConfig.maxRetries,
|
|
1302
1364
|
placeholder: options.placeholder,
|
|
1303
1365
|
disabled: options.disabled,
|
|
1304
1366
|
readOnly: options.readOnly,
|
|
1367
|
+
enterKeyHint: options.enterKeyHint,
|
|
1305
1368
|
debug: sdkConfig.debug
|
|
1306
1369
|
});
|
|
1307
1370
|
if (iframe) iframe.style.opacity = "1";
|
|
@@ -1357,7 +1420,12 @@ const createExpiryElement = (apiKey, sdkConfig, options = {}, coordinatorElement
|
|
|
1357
1420
|
const updatePayload = {
|
|
1358
1421
|
placeholder: newOptions.placeholder,
|
|
1359
1422
|
disabled: newOptions.disabled,
|
|
1360
|
-
readOnly: newOptions.readOnly
|
|
1423
|
+
readOnly: newOptions.readOnly,
|
|
1424
|
+
// Forwarded only when the caller named it, so an explicit
|
|
1425
|
+
// `enterKeyHint: undefined` clears the hint but a partial update keeps it
|
|
1426
|
+
..."enterKeyHint" in newOptions && {
|
|
1427
|
+
enterKeyHint: newOptions.enterKeyHint
|
|
1428
|
+
}
|
|
1361
1429
|
};
|
|
1362
1430
|
if (newOptions.themeMode !== void 0) {
|
|
1363
1431
|
updatePayload.themeMode = newOptions.themeMode;
|
|
@@ -1511,7 +1579,10 @@ const createTextElement = (apiKey, sdkConfig, options = {}, coordinatorElementId
|
|
|
1511
1579
|
theme: sdkConfig.theme,
|
|
1512
1580
|
darkTheme: sdkConfig.darkTheme,
|
|
1513
1581
|
themeMode: sdkConfig.themeMode,
|
|
1582
|
+
direction: sdkConfig.direction,
|
|
1583
|
+
language: sdkConfig.language,
|
|
1514
1584
|
apiKey,
|
|
1585
|
+
environment: sdkConfig.environment,
|
|
1515
1586
|
apiTimeout: sdkConfig.timeoutMs,
|
|
1516
1587
|
apiRetries: sdkConfig.retryConfig.maxRetries,
|
|
1517
1588
|
placeholder: options.placeholder,
|
|
@@ -1523,6 +1594,7 @@ const createTextElement = (apiKey, sdkConfig, options = {}, coordinatorElementId
|
|
|
1523
1594
|
maxLength: options.maxLength,
|
|
1524
1595
|
password: options.password,
|
|
1525
1596
|
inputMode: options.inputMode,
|
|
1597
|
+
enterKeyHint: options.enterKeyHint,
|
|
1526
1598
|
mask: serializedMask,
|
|
1527
1599
|
transform: serializedTransform,
|
|
1528
1600
|
debug: sdkConfig.debug
|
|
@@ -1585,7 +1657,12 @@ const createTextElement = (apiKey, sdkConfig, options = {}, coordinatorElementId
|
|
|
1585
1657
|
required: newOptions.required,
|
|
1586
1658
|
maxLength: newOptions.maxLength,
|
|
1587
1659
|
password: newOptions.password,
|
|
1588
|
-
inputMode: newOptions.inputMode
|
|
1660
|
+
inputMode: newOptions.inputMode,
|
|
1661
|
+
// Forwarded only when the caller named it, so an explicit
|
|
1662
|
+
// `enterKeyHint: undefined` clears the hint but a partial update keeps it
|
|
1663
|
+
..."enterKeyHint" in newOptions && {
|
|
1664
|
+
enterKeyHint: newOptions.enterKeyHint
|
|
1665
|
+
}
|
|
1589
1666
|
};
|
|
1590
1667
|
if (newOptions.themeMode !== void 0) {
|
|
1591
1668
|
updatePayload.themeMode = newOptions.themeMode;
|
|
@@ -1811,16 +1888,21 @@ const warnUnknownKeys = (label, obj, knownKeys, deprecatedKeys) => {
|
|
|
1811
1888
|
);
|
|
1812
1889
|
}
|
|
1813
1890
|
};
|
|
1891
|
+
const VALID_ENVIRONMENTS = ["us", "eu", "test"];
|
|
1814
1892
|
const KNOWN_SDK_KEYS = /* @__PURE__ */ new Set([
|
|
1815
1893
|
"elementsBaseUrl",
|
|
1816
1894
|
"whitelabelDomain",
|
|
1817
1895
|
"apiBaseUrl",
|
|
1896
|
+
"environment",
|
|
1818
1897
|
"debug",
|
|
1819
1898
|
"allowClipboard",
|
|
1899
|
+
"allowHttpClient",
|
|
1820
1900
|
"measurePerformance",
|
|
1821
1901
|
"timeoutMs",
|
|
1822
1902
|
"retryConfig",
|
|
1823
1903
|
"themeMode",
|
|
1904
|
+
"direction",
|
|
1905
|
+
"language",
|
|
1824
1906
|
"theme",
|
|
1825
1907
|
"darkTheme",
|
|
1826
1908
|
"sessionAuthorizationUrl"
|
|
@@ -1868,6 +1950,9 @@ const validateSDKConfig = (options = {}) => {
|
|
|
1868
1950
|
if (options.allowClipboard !== void 0 && typeof options.allowClipboard !== "boolean") {
|
|
1869
1951
|
throw ConfigurationError("allowClipboard must be a boolean");
|
|
1870
1952
|
}
|
|
1953
|
+
if (options.allowHttpClient !== void 0 && typeof options.allowHttpClient !== "boolean") {
|
|
1954
|
+
throw ConfigurationError("allowHttpClient must be a boolean");
|
|
1955
|
+
}
|
|
1871
1956
|
if (options.measurePerformance !== void 0 && typeof options.measurePerformance !== "boolean") {
|
|
1872
1957
|
throw ConfigurationError("measurePerformance must be a boolean");
|
|
1873
1958
|
}
|
|
@@ -1894,6 +1979,20 @@ const validateSDKConfig = (options = {}) => {
|
|
|
1894
1979
|
if (!["light", "dark", "auto"].includes(themeMode)) {
|
|
1895
1980
|
throw ConfigurationError('themeMode must be "light", "dark", or "auto"');
|
|
1896
1981
|
}
|
|
1982
|
+
if (options.environment !== void 0) {
|
|
1983
|
+
if (!VALID_ENVIRONMENTS.includes(options.environment)) {
|
|
1984
|
+
throw ConfigurationError(
|
|
1985
|
+
`environment must be ${VALID_ENVIRONMENTS.map((e) => `"${e}"`).join(", ")}`
|
|
1986
|
+
);
|
|
1987
|
+
}
|
|
1988
|
+
}
|
|
1989
|
+
const direction = options.direction ?? "ltr";
|
|
1990
|
+
if (!["ltr", "rtl"].includes(direction)) {
|
|
1991
|
+
throw ConfigurationError('direction must be "ltr" or "rtl"');
|
|
1992
|
+
}
|
|
1993
|
+
if (options.language !== void 0 && !isLanguageTag(options.language)) {
|
|
1994
|
+
throw ConfigurationError("language must be a BCP 47 language tag");
|
|
1995
|
+
}
|
|
1897
1996
|
if (options.sessionAuthorizationUrl !== void 0) {
|
|
1898
1997
|
if (typeof options.sessionAuthorizationUrl !== "string" || options.sessionAuthorizationUrl.trim() === "") {
|
|
1899
1998
|
throw ConfigurationError("sessionAuthorizationUrl must be a non-empty string");
|
|
@@ -1928,22 +2027,27 @@ const validateSDKConfig = (options = {}) => {
|
|
|
1928
2027
|
}
|
|
1929
2028
|
throw ConfigurationError("whitelabelDomain must be a valid URL");
|
|
1930
2029
|
}
|
|
1931
|
-
const { pathname } = new URL("https://js.basistheory.com/3.
|
|
2030
|
+
const { pathname } = new URL("https://js.basistheory.com/3.1.0/elements");
|
|
1932
2031
|
resolvedBaseUrl = `${domainOrigin}${pathname}`;
|
|
1933
2032
|
}
|
|
1934
|
-
const finalBaseUrl = resolvedBaseUrl || "https://js.basistheory.com/3.
|
|
2033
|
+
const finalBaseUrl = resolvedBaseUrl || "https://js.basistheory.com/3.1.0/elements";
|
|
1935
2034
|
const iframeOrigin = new URL(finalBaseUrl).origin;
|
|
1936
2035
|
return {
|
|
1937
2036
|
iframeOrigin,
|
|
1938
2037
|
elementsBaseUrl: finalBaseUrl,
|
|
1939
2038
|
apiBaseUrl: options.apiBaseUrl,
|
|
1940
2039
|
// Optional - auto-detects if not provided
|
|
2040
|
+
environment: options.environment,
|
|
2041
|
+
// Optional - resolves as before when unset
|
|
1941
2042
|
debug: options.debug ?? false,
|
|
1942
2043
|
allowClipboard: options.allowClipboard ?? false,
|
|
2044
|
+
allowHttpClient: options.allowHttpClient ?? false,
|
|
1943
2045
|
measurePerformance: options.measurePerformance ?? false,
|
|
1944
2046
|
timeoutMs: options.timeoutMs || 3e4,
|
|
1945
2047
|
// 30s default for slow 3G connections
|
|
1946
2048
|
themeMode,
|
|
2049
|
+
direction,
|
|
2050
|
+
language: options.language,
|
|
1947
2051
|
theme: mergeWithDefaultTheme(options.theme),
|
|
1948
2052
|
// Light theme or only theme
|
|
1949
2053
|
darkTheme: options.darkTheme ? mergeWithDefaultTheme(options.darkTheme) : void 0,
|
|
@@ -1957,8 +2061,31 @@ const COMMON_ELEMENT_KEYS = /* @__PURE__ */ new Set([
|
|
|
1957
2061
|
"placeholder",
|
|
1958
2062
|
"ariaLabel",
|
|
1959
2063
|
"disabled",
|
|
1960
|
-
"readOnly"
|
|
2064
|
+
"readOnly",
|
|
2065
|
+
"enterKeyHint"
|
|
2066
|
+
]);
|
|
2067
|
+
const VALID_ENTER_KEY_HINTS = /* @__PURE__ */ new Set([
|
|
2068
|
+
"enter",
|
|
2069
|
+
"done",
|
|
2070
|
+
"go",
|
|
2071
|
+
"next",
|
|
2072
|
+
"previous",
|
|
2073
|
+
"search",
|
|
2074
|
+
"send"
|
|
1961
2075
|
]);
|
|
2076
|
+
const CARD_ENTER_KEY_HINT_FIELDS = /* @__PURE__ */ new Set([
|
|
2077
|
+
"cardNumber",
|
|
2078
|
+
"expiryDate",
|
|
2079
|
+
"cvv",
|
|
2080
|
+
"cvc"
|
|
2081
|
+
]);
|
|
2082
|
+
const validateEnterKeyHintValue = (value, label) => {
|
|
2083
|
+
if (typeof value !== "string" || !VALID_ENTER_KEY_HINTS.has(value)) {
|
|
2084
|
+
throw ConfigurationError(
|
|
2085
|
+
`${label} must be one of: ${Array.from(VALID_ENTER_KEY_HINTS).join(", ")}`
|
|
2086
|
+
);
|
|
2087
|
+
}
|
|
2088
|
+
};
|
|
1962
2089
|
const ELEMENT_TYPE_KEYS = {
|
|
1963
2090
|
cardNumber: /* @__PURE__ */ new Set([...COMMON_ELEMENT_KEYS, "binLookup", "coBadge"]),
|
|
1964
2091
|
cvv: /* @__PURE__ */ new Set([...COMMON_ELEMENT_KEYS, "cardBrand", "cvvLengths"]),
|
|
@@ -2021,6 +2148,23 @@ const validateElementOptions = (type, options = {}) => {
|
|
|
2021
2148
|
if (options.ariaLabel !== void 0 && typeof options.ariaLabel !== "string") {
|
|
2022
2149
|
throw ConfigurationError("ariaLabel must be a string");
|
|
2023
2150
|
}
|
|
2151
|
+
if (options.enterKeyHint !== void 0) {
|
|
2152
|
+
const enterKeyHint = options.enterKeyHint;
|
|
2153
|
+
if (type === "card" && typeof enterKeyHint === "object" && enterKeyHint !== null && !Array.isArray(enterKeyHint)) {
|
|
2154
|
+
warnUnknownKeys(
|
|
2155
|
+
"enterKeyHint",
|
|
2156
|
+
enterKeyHint,
|
|
2157
|
+
CARD_ENTER_KEY_HINT_FIELDS
|
|
2158
|
+
);
|
|
2159
|
+
Object.entries(enterKeyHint).filter(([field]) => CARD_ENTER_KEY_HINT_FIELDS.has(field)).forEach(([field, value]) => {
|
|
2160
|
+
if (value !== void 0) {
|
|
2161
|
+
validateEnterKeyHintValue(value, `enterKeyHint.${field}`);
|
|
2162
|
+
}
|
|
2163
|
+
});
|
|
2164
|
+
} else {
|
|
2165
|
+
validateEnterKeyHintValue(enterKeyHint, "enterKeyHint");
|
|
2166
|
+
}
|
|
2167
|
+
}
|
|
2024
2168
|
if (type === "text") {
|
|
2025
2169
|
if (options.maxLength !== void 0) {
|
|
2026
2170
|
if (typeof options.maxLength !== "number" || options.maxLength <= 0) {
|
|
@@ -2227,21 +2371,21 @@ const BasisTheory = (apiKey, options = {}, queuedCommands) => {
|
|
|
2227
2371
|
let cardDisplayElementFactory = null;
|
|
2228
2372
|
const lazyCardElement = async () => {
|
|
2229
2373
|
if (!cardElementFactory) {
|
|
2230
|
-
const module = await import("./create-card-
|
|
2374
|
+
const module = await import("./create-card-CoTyU6ju.js");
|
|
2231
2375
|
cardElementFactory = module.createCardElement;
|
|
2232
2376
|
}
|
|
2233
2377
|
return cardElementFactory;
|
|
2234
2378
|
};
|
|
2235
2379
|
const lazyCopyButtonElement = async () => {
|
|
2236
2380
|
if (!copyButtonElementFactory) {
|
|
2237
|
-
const module = await import("./create-copy-button-
|
|
2381
|
+
const module = await import("./create-copy-button-D8VeinHW.js");
|
|
2238
2382
|
copyButtonElementFactory = module.createCopyButtonElement;
|
|
2239
2383
|
}
|
|
2240
2384
|
return copyButtonElementFactory;
|
|
2241
2385
|
};
|
|
2242
2386
|
const lazyCardDisplayElement = async () => {
|
|
2243
2387
|
if (!cardDisplayElementFactory) {
|
|
2244
|
-
const module = await import("./create-card-display-
|
|
2388
|
+
const module = await import("./create-card-display-DQmTA_8S.js");
|
|
2245
2389
|
cardDisplayElementFactory = module.createCardDisplayElement;
|
|
2246
2390
|
}
|
|
2247
2391
|
return cardDisplayElementFactory;
|
|
@@ -2336,11 +2480,15 @@ const BasisTheory = (apiKey, options = {}, queuedCommands) => {
|
|
|
2336
2480
|
apiKey,
|
|
2337
2481
|
apiBaseUrl: config.apiBaseUrl,
|
|
2338
2482
|
// Optional - auto-detects if not provided
|
|
2483
|
+
environment: config.environment,
|
|
2484
|
+
// Optional - resolves as before when unset
|
|
2339
2485
|
apiTimeout: 3e4,
|
|
2340
2486
|
apiRetries: 3,
|
|
2341
2487
|
// Frozen by the coordinator on this first config; copy references are
|
|
2342
2488
|
// refused unless it's enabled here.
|
|
2343
2489
|
allowClipboard: config.allowClipboard,
|
|
2490
|
+
// Frozen alongside allowClipboard; bt.client.* is refused unless enabled here.
|
|
2491
|
+
allowHttpClient: config.allowHttpClient,
|
|
2344
2492
|
debug: config.debug || false,
|
|
2345
2493
|
theme: config.theme,
|
|
2346
2494
|
darkTheme: config.darkTheme,
|
|
@@ -2794,6 +2942,61 @@ const BasisTheory = (apiKey, options = {}, queuedCommands) => {
|
|
|
2794
2942
|
delete: proxyVerb("DELETE")
|
|
2795
2943
|
};
|
|
2796
2944
|
})(),
|
|
2945
|
+
client: (() => {
|
|
2946
|
+
const invokeClient = guardAsync(async (method, url, body, options2 = {}) => {
|
|
2947
|
+
if (!config.allowHttpClient) {
|
|
2948
|
+
throw ConfigurationError(
|
|
2949
|
+
"bt.client requires allowHttpClient: true on BasisTheory() initialization. Sending card data to a third party may affect PCI scope and must be enabled deliberately.",
|
|
2950
|
+
{ received: config.allowHttpClient, expected: true }
|
|
2951
|
+
);
|
|
2952
|
+
}
|
|
2953
|
+
validateDestinationRequest({ url, method, headers: options2 == null ? void 0 : options2.headers });
|
|
2954
|
+
log2("client invoked", { method, hasBody: body !== void 0 });
|
|
2955
|
+
if (!coordinatorClient) {
|
|
2956
|
+
log2("Waiting for coordinator initialization");
|
|
2957
|
+
await initializeCoordinator();
|
|
2958
|
+
}
|
|
2959
|
+
if (!coordinatorClient) {
|
|
2960
|
+
throw CoordinatorError("Coordinator failed to initialize");
|
|
2961
|
+
}
|
|
2962
|
+
const resolvedBody = body !== void 0 ? resolveElementReferences(body) : void 0;
|
|
2963
|
+
try {
|
|
2964
|
+
const result = await coordinatorClient.sendRequest(
|
|
2965
|
+
"CMD_HTTP_CLIENT",
|
|
2966
|
+
{
|
|
2967
|
+
method,
|
|
2968
|
+
url,
|
|
2969
|
+
headers: options2 == null ? void 0 : options2.headers,
|
|
2970
|
+
body: resolvedBody
|
|
2971
|
+
},
|
|
2972
|
+
{ retries: 0 }
|
|
2973
|
+
);
|
|
2974
|
+
log2("client successful", { method });
|
|
2975
|
+
return result;
|
|
2976
|
+
} catch (error) {
|
|
2977
|
+
log2("client failed", { method, error: error.message });
|
|
2978
|
+
const transportError = error;
|
|
2979
|
+
if (transportError.code === "HTTP_CLIENT_ERROR") {
|
|
2980
|
+
throw HttpClientError(
|
|
2981
|
+
transportError.message.replace(/^\[HTTP_CLIENT_ERROR\] /, ""),
|
|
2982
|
+
transportError.status ?? -1,
|
|
2983
|
+
transportError.data,
|
|
2984
|
+
transportError.headers
|
|
2985
|
+
);
|
|
2986
|
+
}
|
|
2987
|
+
throw error;
|
|
2988
|
+
}
|
|
2989
|
+
});
|
|
2990
|
+
const withBody = (method) => (url, body, options2) => invokeClient(method, url, body, options2 ?? {});
|
|
2991
|
+
const withoutBody = (method) => (url, options2) => invokeClient(method, url, void 0, options2 ?? {});
|
|
2992
|
+
return {
|
|
2993
|
+
get: withoutBody("GET"),
|
|
2994
|
+
post: withBody("POST"),
|
|
2995
|
+
put: withBody("PUT"),
|
|
2996
|
+
patch: withBody("PATCH"),
|
|
2997
|
+
delete: withoutBody("DELETE")
|
|
2998
|
+
};
|
|
2999
|
+
})(),
|
|
2797
3000
|
updateThemeMode: guardAsync(async (mode) => {
|
|
2798
3001
|
log2("updateThemeMode called", {
|
|
2799
3002
|
oldMode: currentThemeMode,
|
|
@@ -2960,8 +3163,8 @@ const BasisTheory = (apiKey, options = {}, queuedCommands) => {
|
|
|
2960
3163
|
if (typeof window !== "undefined" && typeof document !== "undefined" && document.currentScript && !window.BasisTheory) {
|
|
2961
3164
|
window.BasisTheory = BasisTheory;
|
|
2962
3165
|
}
|
|
2963
|
-
const version = "3.
|
|
2964
|
-
const buildDate = "2026-
|
|
3166
|
+
const version = "3.1.0";
|
|
3167
|
+
const buildDate = "2026-09-21T19:33:43.220Z";
|
|
2965
3168
|
if (typeof window !== "undefined") {
|
|
2966
3169
|
window.__BasisTheorySDK__ = BasisTheory;
|
|
2967
3170
|
}
|