@ozura/elements 1.1.0 → 1.2.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.
@@ -840,6 +840,85 @@ function validateBilling(billing) {
840
840
  */
841
841
  const PROTOCOL_VERSION = 1;
842
842
 
843
+ /**
844
+ * Creates a `getSessionKey` callback for `OzVault.create()` and `<OzElements>`.
845
+ *
846
+ * This is the recommended way to wire the SDK to your backend session endpoint.
847
+ * If you don't need custom headers or auth logic, pass `sessionUrl` directly to
848
+ * `OzVault.create()` or `<OzElements>` — it calls this helper internally.
849
+ *
850
+ * The callback POSTs `{ sessionId }` to `url` and reads `sessionKey` (or the
851
+ * legacy `waxKey`) from the JSON response, so it is compatible with both the
852
+ * new `createSessionMiddleware` and the old `createMintWaxMiddleware` backends.
853
+ *
854
+ * Each call enforces a **10-second timeout**. On pure network failures
855
+ * (offline, DNS, connection refused) the request is retried **once after 750ms**.
856
+ * HTTP 4xx/5xx errors are never retried — they indicate misconfiguration.
857
+ *
858
+ * @param url - Absolute or relative URL of your session endpoint, e.g. `'/api/oz-session'`.
859
+ *
860
+ * @example
861
+ * // Simplest — just pass sessionUrl, no need to call this directly
862
+ * const vault = await OzVault.create({ pubKey: 'pk_live_...', sessionUrl: '/api/oz-session' });
863
+ *
864
+ * @example
865
+ * // Manual — use when you need custom headers
866
+ * const vault = await OzVault.create({
867
+ * pubKey: 'pk_live_...',
868
+ * getSessionKey: createSessionFetcher('/api/oz-session'),
869
+ * });
870
+ */
871
+ function createSessionFetcher(url) {
872
+ const TIMEOUT_MS = 10000;
873
+ // Each attempt gets its own AbortController so a timeout on attempt 1 does
874
+ // not bleed into the retry.
875
+ const attemptFetch = (sessionId) => {
876
+ const controller = new AbortController();
877
+ const timer = setTimeout(() => controller.abort(), TIMEOUT_MS);
878
+ return fetch(url, {
879
+ method: 'POST',
880
+ headers: { 'Content-Type': 'application/json' },
881
+ body: JSON.stringify({ sessionId }),
882
+ signal: controller.signal,
883
+ }).finally(() => clearTimeout(timer));
884
+ };
885
+ return async (sessionId) => {
886
+ let res;
887
+ try {
888
+ res = await attemptFetch(sessionId);
889
+ }
890
+ catch (firstErr) {
891
+ // Timeout/abort — don't retry, we already waited the full duration.
892
+ if (firstErr instanceof Error && (firstErr.name === 'AbortError' || firstErr.name === 'TimeoutError')) {
893
+ throw new OzError(`Session endpoint timed out after ${TIMEOUT_MS / 1000}s (${url})`, undefined, 'timeout');
894
+ }
895
+ // Pure network error — retry once after a short pause.
896
+ await new Promise(resolve => setTimeout(resolve, 750));
897
+ try {
898
+ res = await attemptFetch(sessionId);
899
+ }
900
+ catch (retryErr) {
901
+ const msg = retryErr instanceof Error ? retryErr.message : 'Network error';
902
+ throw new OzError(`Could not reach session endpoint (${url}): ${msg}`, undefined, 'network');
903
+ }
904
+ }
905
+ const data = await res.json().catch(() => ({}));
906
+ if (!res.ok) {
907
+ throw new OzError(typeof data.error === 'string' && data.error
908
+ ? data.error
909
+ : `Session endpoint returned HTTP ${res.status}`, undefined, res.status >= 500 ? 'server' : res.status === 401 || res.status === 403 ? 'auth' : 'validation');
910
+ }
911
+ // Accept both new `sessionKey` and legacy `waxKey` for backward compatibility
912
+ // with backends that haven't migrated to createSessionMiddleware yet.
913
+ const key = (typeof data.sessionKey === 'string' ? data.sessionKey : '') ||
914
+ (typeof data.waxKey === 'string' ? data.waxKey : '');
915
+ if (!key.trim()) {
916
+ throw new OzError('Session endpoint response is missing sessionKey. Check your /api/oz-session implementation.', undefined, 'validation');
917
+ }
918
+ return key;
919
+ };
920
+ }
921
+
843
922
  function isCardMetadata(v) {
844
923
  return !!v && typeof v === 'object' && typeof v.last4 === 'string';
845
924
  }
@@ -879,7 +958,7 @@ class OzVault {
879
958
  * @internal
880
959
  */
881
960
  constructor(options, waxKey, tokenizationSessionId) {
882
- var _a, _b, _c, _d;
961
+ var _a, _b, _c, _d, _e;
883
962
  this.elements = new Map();
884
963
  this.elementsByType = new Map();
885
964
  this.bankElementsByType = new Map();
@@ -913,7 +992,12 @@ class OzVault {
913
992
  this.fonts = (_a = options.fonts) !== null && _a !== void 0 ? _a : [];
914
993
  this.resolvedAppearance = resolveAppearance(options.appearance);
915
994
  this.vaultId = `vault-${uuid()}`;
916
- this._maxTokenizeCalls = (_b = options.maxTokenizeCalls) !== null && _b !== void 0 ? _b : 3;
995
+ // sessionLimit takes precedence over legacy maxTokenizeCalls.
996
+ // null means unlimited — use Infinity so the ">=" check never triggers.
997
+ const rawLimit = options.sessionLimit !== undefined
998
+ ? options.sessionLimit
999
+ : ((_b = options.maxTokenizeCalls) !== null && _b !== void 0 ? _b : 3);
1000
+ this._maxTokenizeCalls = rawLimit === null ? Infinity : rawLimit;
917
1001
  this._debug = (_c = options.debug) !== null && _c !== void 0 ? _c : false;
918
1002
  this.boundHandleMessage = this.handleMessage.bind(this);
919
1003
  window.addEventListener('message', this.boundHandleMessage);
@@ -929,7 +1013,8 @@ class OzVault {
929
1013
  }
930
1014
  }, timeout);
931
1015
  }
932
- this._onWaxRefresh = options.onWaxRefresh;
1016
+ // onSessionRefresh takes precedence over legacy onWaxRefresh
1017
+ this._onWaxRefresh = (_e = options.onSessionRefresh) !== null && _e !== void 0 ? _e : options.onWaxRefresh;
933
1018
  this._onReady = options.onReady;
934
1019
  this.log('vault created', { vaultId: this.vaultId, frameBaseUrl: this.frameBaseUrl, maxTokenizeCalls: this._maxTokenizeCalls });
935
1020
  }
@@ -937,51 +1022,63 @@ class OzVault {
937
1022
  * Creates and returns a ready `OzVault` instance.
938
1023
  *
939
1024
  * Internally this:
940
- * 1. Generates a `tokenizationSessionId` (UUID).
1025
+ * 1. Generates a session UUID.
941
1026
  * 2. Starts loading the hidden tokenizer iframe immediately.
942
- * 3. Calls `options.fetchWaxKey(tokenizationSessionId)` concurrently — your
943
- * backend mints a session-bound wax key from the vault and returns it.
944
- * 4. Resolves with the vault instance once the wax key is stored. The iframe
1027
+ * 3. Fetches a session key from your backend concurrently — either via
1028
+ * `sessionUrl` (simplest), `getSessionKey` (custom headers/auth), or the
1029
+ * deprecated `fetchWaxKey` callback.
1030
+ * 4. Resolves with the vault instance once the session key is stored. The iframe
945
1031
  * has been loading the whole time, so `isReady` may already be true or
946
1032
  * will fire shortly after.
947
1033
  *
948
1034
  * The returned vault is ready to create elements immediately. `createToken()`
949
1035
  * additionally requires `vault.isReady` (tokenizer iframe loaded).
950
1036
  *
951
- * @throws {OzError} if `fetchWaxKey` throws, returns a non-string value, or returns an empty/whitespace-only string.
1037
+ * @throws {OzError} if the session fetch fails, times out, or returns an empty string.
952
1038
  */
953
1039
  static async create(options, signal) {
954
1040
  if (!options.pubKey || !options.pubKey.trim()) {
955
1041
  throw new OzError('pubKey is required in options. Obtain your public key from the Ozura admin.');
956
1042
  }
957
- if (typeof options.fetchWaxKey !== 'function') {
958
- throw new OzError('fetchWaxKey must be a function. See OzVault.create() docs for the expected signature.');
1043
+ // Normalize the session callback. Priority: sessionUrl > getSessionKey > fetchWaxKey (deprecated).
1044
+ // This allows merchants to use the clean new API without touching legacy code.
1045
+ let resolvedFetchKey;
1046
+ if (options.sessionUrl) {
1047
+ resolvedFetchKey = createSessionFetcher(options.sessionUrl);
1048
+ }
1049
+ else if (typeof options.getSessionKey === 'function') {
1050
+ resolvedFetchKey = options.getSessionKey;
1051
+ }
1052
+ else if (typeof options.fetchWaxKey === 'function') {
1053
+ resolvedFetchKey = options.fetchWaxKey;
1054
+ }
1055
+ else {
1056
+ throw new OzError('A session URL or callback is required. Pass sessionUrl, getSessionKey, or fetchWaxKey to OzVault.create().');
959
1057
  }
960
1058
  const tokenizationSessionId = uuid();
961
1059
  // Construct the vault immediately — this mounts the tokenizer iframe so it
962
- // starts loading while fetchWaxKey is in flight. The waxKey field starts
963
- // empty and is set below before create() returns.
1060
+ // starts loading while the session fetch is in flight.
964
1061
  const vault = new OzVault(options, '', tokenizationSessionId);
965
1062
  // If the caller provides an AbortSignal (e.g. React useEffect cleanup),
966
1063
  // destroy the vault immediately on abort so the tokenizer iframe and message
967
- // listener are removed synchronously rather than waiting for fetchWaxKey to
968
- // settle. This eliminates the brief double-iframe window in React StrictMode.
1064
+ // listener are removed synchronously rather than waiting for the session fetch
1065
+ // to settle. This eliminates the brief double-iframe window in React StrictMode.
969
1066
  const onAbort = () => vault.destroy();
970
1067
  signal === null || signal === void 0 ? void 0 : signal.addEventListener('abort', onAbort, { once: true });
971
1068
  let waxKey;
972
1069
  try {
973
- waxKey = await options.fetchWaxKey(tokenizationSessionId);
1070
+ waxKey = await resolvedFetchKey(tokenizationSessionId);
974
1071
  }
975
1072
  catch (err) {
976
1073
  signal === null || signal === void 0 ? void 0 : signal.removeEventListener('abort', onAbort);
977
1074
  vault.destroy();
978
1075
  if (signal === null || signal === void 0 ? void 0 : signal.aborted)
979
1076
  throw new OzError('OzVault.create() was cancelled.');
980
- // Preserve errorCode/retryable from OzError (e.g. timeout/network from createFetchWaxKey)
1077
+ // Preserve errorCode/retryable from OzError (e.g. timeout/network from createSessionFetcher)
981
1078
  // so callers can distinguish transient failures from config errors.
982
1079
  const originalCode = err instanceof OzError ? err.errorCode : undefined;
983
1080
  const msg = err instanceof Error ? err.message : 'Unknown error';
984
- throw new OzError(`fetchWaxKey threw an error: ${msg}`, undefined, originalCode);
1081
+ throw new OzError(`Session fetch threw an error: ${msg}`, undefined, originalCode);
985
1082
  }
986
1083
  signal === null || signal === void 0 ? void 0 : signal.removeEventListener('abort', onAbort);
987
1084
  if (signal === null || signal === void 0 ? void 0 : signal.aborted) {
@@ -990,11 +1087,11 @@ class OzVault {
990
1087
  }
991
1088
  if (typeof waxKey !== 'string' || !waxKey.trim()) {
992
1089
  vault.destroy();
993
- throw new OzError('fetchWaxKey must return a non-empty wax key string. Check your mint endpoint.');
1090
+ throw new OzError('Session fetch returned an empty key. Check your session endpoint response — it must return { sessionKey: "..." }.');
994
1091
  }
995
1092
  // Static methods can access private fields of instances of the same class.
996
1093
  vault.waxKey = waxKey;
997
- vault._storedFetchWaxKey = options.fetchWaxKey;
1094
+ vault._storedFetchWaxKey = resolvedFetchKey;
998
1095
  // If the tokenizer iframe fired OZ_FRAME_READY before fetchWaxKey resolved,
999
1096
  // the OZ_INIT sent at that point had an empty waxKey. Send a follow-up now
1000
1097
  // so the tokenizer has the key stored before any createToken() call.
@@ -1660,9 +1757,9 @@ class OzVault {
1660
1757
  // key without waiting for a vault rejection.
1661
1758
  this._tokenizeSuccessCount++;
1662
1759
  if (this._tokenizeSuccessCount >= this._maxTokenizeCalls) {
1663
- this.log('proactive wax key refresh triggered', { tokenizeSuccessCount: this._tokenizeSuccessCount, maxTokenizeCalls: this._maxTokenizeCalls });
1760
+ this.log('proactive session key refresh triggered', { tokenizeSuccessCount: this._tokenizeSuccessCount, maxTokenizeCalls: this._maxTokenizeCalls });
1664
1761
  this.refreshWaxKey().catch((err) => {
1665
- console.warn('[OzVault] Post-budget wax key refresh failed:', err instanceof Error ? err.message : err);
1762
+ console.warn('[OzVault] Post-budget session key refresh failed:', err instanceof Error ? err.message : err);
1666
1763
  });
1667
1764
  }
1668
1765
  }
@@ -1820,9 +1917,9 @@ class OzVault {
1820
1917
  // Same proactive refresh logic as card tokenization.
1821
1918
  this._tokenizeSuccessCount++;
1822
1919
  if (this._tokenizeSuccessCount >= this._maxTokenizeCalls) {
1823
- this.log('proactive wax key refresh triggered', { tokenizeSuccessCount: this._tokenizeSuccessCount, maxTokenizeCalls: this._maxTokenizeCalls });
1920
+ this.log('proactive session key refresh triggered', { tokenizeSuccessCount: this._tokenizeSuccessCount, maxTokenizeCalls: this._maxTokenizeCalls });
1824
1921
  this.refreshWaxKey().catch((err) => {
1825
- console.warn('[OzVault] Post-budget wax key refresh failed:', err instanceof Error ? err.message : err);
1922
+ console.warn('[OzVault] Post-budget session key refresh failed:', err instanceof Error ? err.message : err);
1826
1923
  });
1827
1924
  }
1828
1925
  }
@@ -1908,84 +2005,6 @@ class OzVault {
1908
2005
  }
1909
2006
  }
1910
2007
 
1911
- /**
1912
- * Creates a ready-to-use `fetchWaxKey` callback for `OzVault.create()` and `<OzElements>`.
1913
- *
1914
- * Calls your backend mint endpoint with `{ sessionId }` and returns the wax key string.
1915
- * Throws on non-OK responses or a missing `waxKey` field so the vault can surface the
1916
- * error through its normal error path.
1917
- *
1918
- * Each call enforces a 10-second per-attempt timeout. On a pure network-level
1919
- * failure (connection refused, DNS failure, etc.) the call is retried once after
1920
- * 750ms before throwing. HTTP errors (4xx/5xx) are never retried — they indicate
1921
- * an endpoint misconfiguration or an invalid key, not a transient failure.
1922
- *
1923
- * The mint endpoint is typically the one-line `createMintWaxHandler` / `createMintWaxMiddleware`
1924
- * from `@ozura/elements/server`.
1925
- *
1926
- * @param mintUrl - Absolute or relative URL of your wax-key mint endpoint, e.g. `'/api/mint-wax'`.
1927
- *
1928
- * @example
1929
- * // Vanilla JS
1930
- * const vault = await OzVault.create({
1931
- * pubKey: 'pk_live_...',
1932
- * fetchWaxKey: createFetchWaxKey('/api/mint-wax'),
1933
- * });
1934
- *
1935
- * @example
1936
- * // React
1937
- * <OzElements pubKey="pk_live_..." fetchWaxKey={createFetchWaxKey('/api/mint-wax')}>
1938
- */
1939
- function createFetchWaxKey(mintUrl) {
1940
- const TIMEOUT_MS = 10000;
1941
- // Each attempt gets its own AbortController so a timeout on attempt 1 does
1942
- // not bleed into the retry. Uses AbortController + setTimeout instead of
1943
- // AbortSignal.timeout() to support environments without that API.
1944
- const attemptFetch = (sessionId) => {
1945
- const controller = new AbortController();
1946
- const timer = setTimeout(() => controller.abort(), TIMEOUT_MS);
1947
- return fetch(mintUrl, {
1948
- method: 'POST',
1949
- headers: { 'Content-Type': 'application/json' },
1950
- body: JSON.stringify({ sessionId }),
1951
- signal: controller.signal,
1952
- }).finally(() => clearTimeout(timer));
1953
- };
1954
- return async (sessionId) => {
1955
- let res;
1956
- try {
1957
- res = await attemptFetch(sessionId);
1958
- }
1959
- catch (firstErr) {
1960
- // Abort/timeout should not be retried — the server received nothing or
1961
- // we already waited the full timeout duration.
1962
- if (firstErr instanceof Error && (firstErr.name === 'AbortError' || firstErr.name === 'TimeoutError')) {
1963
- throw new OzError(`Wax key mint timed out after ${TIMEOUT_MS / 1000}s (${mintUrl})`, undefined, 'timeout');
1964
- }
1965
- // Pure network error (offline, DNS, connection refused) — retry once
1966
- // after a short pause in case of a transient blip.
1967
- await new Promise(resolve => setTimeout(resolve, 750));
1968
- try {
1969
- res = await attemptFetch(sessionId);
1970
- }
1971
- catch (retryErr) {
1972
- const msg = retryErr instanceof Error ? retryErr.message : 'Network error';
1973
- throw new OzError(`Could not reach wax key mint endpoint (${mintUrl}): ${msg}`, undefined, 'network');
1974
- }
1975
- }
1976
- const data = await res.json().catch(() => ({}));
1977
- if (!res.ok) {
1978
- throw new OzError(typeof data.error === 'string' && data.error
1979
- ? data.error
1980
- : `Wax key mint failed (HTTP ${res.status})`, undefined, res.status >= 500 ? 'server' : res.status === 401 || res.status === 403 ? 'auth' : 'validation');
1981
- }
1982
- if (typeof data.waxKey !== 'string' || !data.waxKey.trim()) {
1983
- throw new OzError('Mint endpoint response is missing waxKey. Check your /api/mint-wax implementation.', undefined, 'validation');
1984
- }
1985
- return data.waxKey;
1986
- };
1987
- }
1988
-
1989
2008
  const OzContext = react.createContext({
1990
2009
  vault: null,
1991
2010
  initError: null,
@@ -2002,7 +2021,7 @@ const OzContext = react.createContext({
2002
2021
  * All `<OzCardNumber />`, `<OzExpiry />`, and `<OzCvv />` children must be
2003
2022
  * rendered inside this provider.
2004
2023
  */
2005
- function OzElements({ fetchWaxKey, pubKey, frameBaseUrl, fonts, onLoadError, loadTimeoutMs, onWaxRefresh, onReady, appearance, maxTokenizeCalls, debug, children }) {
2024
+ function OzElements({ sessionUrl, getSessionKey, fetchWaxKey, pubKey, frameBaseUrl, fonts, onLoadError, loadTimeoutMs, onSessionRefresh, onWaxRefresh, onReady, appearance, sessionLimit, maxTokenizeCalls, debug, children }) {
2006
2025
  const [vault, setVault] = react.useState(null);
2007
2026
  const [initError, setInitError] = react.useState(null);
2008
2027
  const [mountedCount, setMountedCount] = react.useState(0);
@@ -2010,13 +2029,14 @@ function OzElements({ fetchWaxKey, pubKey, frameBaseUrl, fonts, onLoadError, loa
2010
2029
  const [tokenizeCount, setTokenizeCount] = react.useState(0);
2011
2030
  const onLoadErrorRef = react.useRef(onLoadError);
2012
2031
  onLoadErrorRef.current = onLoadError;
2013
- const onWaxRefreshRef = react.useRef(onWaxRefresh);
2014
- onWaxRefreshRef.current = onWaxRefresh;
2032
+ const onWaxRefreshRef = react.useRef(onSessionRefresh !== null && onSessionRefresh !== void 0 ? onSessionRefresh : onWaxRefresh);
2033
+ onWaxRefreshRef.current = onSessionRefresh !== null && onSessionRefresh !== void 0 ? onSessionRefresh : onWaxRefresh;
2015
2034
  const onReadyRef = react.useRef(onReady);
2016
2035
  onReadyRef.current = onReady;
2017
- // Keep a ref to fetchWaxKey so changes don't trigger vault recreation
2018
- const fetchWaxKeyRef = react.useRef(fetchWaxKey);
2019
- fetchWaxKeyRef.current = fetchWaxKey;
2036
+ // Keep a ref to the session callback so changes don't trigger vault recreation.
2037
+ // Priority mirrors OzVault.create(): sessionUrl > getSessionKey > fetchWaxKey.
2038
+ const getSessionKeyRef = react.useRef(getSessionKey !== null && getSessionKey !== void 0 ? getSessionKey : fetchWaxKey);
2039
+ getSessionKeyRef.current = getSessionKey !== null && getSessionKey !== void 0 ? getSessionKey : fetchWaxKey;
2020
2040
  const appearanceKey = react.useMemo(() => appearance ? JSON.stringify(appearance) : '', [appearance]);
2021
2041
  const fontsKey = react.useMemo(() => fonts ? JSON.stringify(fonts) : '', [fonts]);
2022
2042
  react.useEffect(() => {
@@ -2043,7 +2063,11 @@ function OzElements({ fetchWaxKey, pubKey, frameBaseUrl, fonts, onLoadError, loa
2043
2063
  // synchronously rather than waiting for the promise to settle. Without this,
2044
2064
  // two hidden iframes and two window listeners briefly coexist.
2045
2065
  const abortController = new AbortController();
2046
- OzVault.create(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({ pubKey, fetchWaxKey: (sessionId) => fetchWaxKeyRef.current(sessionId) }, (frameBaseUrl ? { frameBaseUrl } : {})), (parsedFonts ? { fonts: parsedFonts } : {})), (parsedAppearance ? { appearance: parsedAppearance } : {})), (onLoadErrorRef.current ? { onLoadError: fireLoadError, loadTimeoutMs } : {})), {
2066
+ OzVault.create(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({ pubKey }, (sessionUrl
2067
+ ? { sessionUrl }
2068
+ : getSessionKeyRef.current
2069
+ ? { getSessionKey: (sessionId) => getSessionKeyRef.current(sessionId) }
2070
+ : {})), (frameBaseUrl ? { frameBaseUrl } : {})), (parsedFonts ? { fonts: parsedFonts } : {})), (parsedAppearance ? { appearance: parsedAppearance } : {})), (onLoadErrorRef.current ? { onLoadError: fireLoadError, loadTimeoutMs } : {})), {
2047
2071
  // Always install onWaxRefresh internally so we can reset tokenizeCount
2048
2072
  // when any wax key refresh occurs (reactive TTL expiry, post-budget
2049
2073
  // proactive, or visibility-change proactive). Without this the React
@@ -2065,11 +2089,12 @@ function OzElements({ fetchWaxKey, pubKey, frameBaseUrl, fonts, onLoadError, loa
2065
2089
  // the retry tokenization completes (a full fetchWaxKey + tokenize round-
2066
2090
  // trip separates them), so the count correctly resets to 0 then rises to
2067
2091
  // 1 after the retry notifyTokenize fires.
2068
- onWaxRefresh: () => {
2092
+ onSessionRefresh: () => {
2069
2093
  var _a;
2070
2094
  Promise.resolve().then(() => setTokenizeCount(0));
2071
2095
  (_a = onWaxRefreshRef.current) === null || _a === void 0 ? void 0 : _a.call(onWaxRefreshRef);
2072
- }, onReady: () => { var _a; return (_a = onReadyRef.current) === null || _a === void 0 ? void 0 : _a.call(onReadyRef); } }), (maxTokenizeCalls !== undefined ? { maxTokenizeCalls } : {})), (debug ? { debug: true } : {})), abortController.signal).then(v => {
2096
+ }, onReady: () => { var _a; return (_a = onReadyRef.current) === null || _a === void 0 ? void 0 : _a.call(onReadyRef); } }), (sessionLimit !== undefined ? { sessionLimit }
2097
+ : maxTokenizeCalls !== undefined ? { maxTokenizeCalls } : {})), (debug ? { debug: true } : {})), abortController.signal).then(v => {
2073
2098
  if (cancelled) {
2074
2099
  v.destroy();
2075
2100
  return;
@@ -2102,7 +2127,7 @@ function OzElements({ fetchWaxKey, pubKey, frameBaseUrl, fonts, onLoadError, loa
2102
2127
  setVault(null);
2103
2128
  setInitError(null);
2104
2129
  };
2105
- }, [pubKey, frameBaseUrl, loadTimeoutMs, appearanceKey, fontsKey, maxTokenizeCalls, debug]);
2130
+ }, [pubKey, sessionUrl, frameBaseUrl, loadTimeoutMs, appearanceKey, fontsKey, sessionLimit, maxTokenizeCalls, debug]);
2106
2131
  const notifyMount = react.useCallback(() => setMountedCount(n => n + 1), []);
2107
2132
  const notifyReady = react.useCallback(() => setReadyCount(n => n + 1), []);
2108
2133
  const notifyUnmount = react.useCallback(() => {
@@ -2446,6 +2471,7 @@ exports.OzCardNumber = OzCardNumber;
2446
2471
  exports.OzCvv = OzCvv;
2447
2472
  exports.OzElements = OzElements;
2448
2473
  exports.OzExpiry = OzExpiry;
2449
- exports.createFetchWaxKey = createFetchWaxKey;
2474
+ exports.createFetchWaxKey = createSessionFetcher;
2475
+ exports.createSessionFetcher = createSessionFetcher;
2450
2476
  exports.useOzElements = useOzElements;
2451
2477
  //# sourceMappingURL=index.cjs.js.map