@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.
- package/README.md +1340 -1338
- package/dist/frame/element-frame.html +22 -22
- package/dist/frame/tokenizer-frame.html +11 -11
- package/dist/oz-elements.esm.js +262 -243
- package/dist/oz-elements.esm.js.map +1 -1
- package/dist/oz-elements.umd.js +263 -243
- package/dist/oz-elements.umd.js.map +1 -1
- package/dist/react/index.cjs.js +138 -112
- package/dist/react/index.cjs.js.map +1 -1
- package/dist/react/index.esm.js +137 -112
- package/dist/react/index.esm.js.map +1 -1
- package/dist/react/react/index.d.ts +50 -29
- package/dist/react/sdk/OzVault.d.ts +6 -5
- package/dist/react/sdk/createSessionFetcher.d.ts +29 -0
- package/dist/react/sdk/index.d.ts +6 -26
- package/dist/react/server/index.d.ts +126 -74
- package/dist/react/types/index.d.ts +56 -31
- package/dist/server/index.cjs.js +165 -76
- package/dist/server/index.cjs.js.map +1 -1
- package/dist/server/index.esm.js +164 -77
- package/dist/server/index.esm.js.map +1 -1
- package/dist/server/sdk/OzVault.d.ts +6 -5
- package/dist/server/sdk/createSessionFetcher.d.ts +29 -0
- package/dist/server/sdk/index.d.ts +6 -26
- package/dist/server/server/index.d.ts +126 -74
- package/dist/server/types/index.d.ts +56 -31
- package/dist/types/sdk/OzVault.d.ts +6 -5
- package/dist/types/sdk/createSessionFetcher.d.ts +29 -0
- package/dist/types/sdk/index.d.ts +6 -26
- package/dist/types/server/index.d.ts +126 -74
- package/dist/types/types/index.d.ts +56 -31
- package/package.json +1 -1
package/dist/react/index.cjs.js
CHANGED
|
@@ -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
|
-
|
|
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
|
-
|
|
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
|
|
1025
|
+
* 1. Generates a session UUID.
|
|
941
1026
|
* 2. Starts loading the hidden tokenizer iframe immediately.
|
|
942
|
-
* 3.
|
|
943
|
-
*
|
|
944
|
-
*
|
|
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
|
|
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
|
-
|
|
958
|
-
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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(`
|
|
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('
|
|
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 =
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
2018
|
-
|
|
2019
|
-
|
|
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(
|
|
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
|
-
|
|
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); } }), (
|
|
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 =
|
|
2474
|
+
exports.createFetchWaxKey = createSessionFetcher;
|
|
2475
|
+
exports.createSessionFetcher = createSessionFetcher;
|
|
2450
2476
|
exports.useOzElements = useOzElements;
|
|
2451
2477
|
//# sourceMappingURL=index.cjs.js.map
|