@flonkid/kyc 1.7.0 → 1.8.1
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/index.cjs +122 -40
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +37 -2
- package/dist/index.d.ts +37 -2
- package/dist/index.js +122 -41
- package/dist/index.js.map +1 -1
- package/dist/server.cjs +1 -1
- package/dist/server.cjs.map +1 -1
- package/dist/server.d.cts +1 -1
- package/dist/server.d.ts +1 -1
- package/dist/server.js +1 -1
- package/dist/server.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -4,7 +4,7 @@ var react = require('react');
|
|
|
4
4
|
var jsxRuntime = require('react/jsx-runtime');
|
|
5
5
|
|
|
6
6
|
// src/shared/constants.ts
|
|
7
|
-
var SDK_VERSION = "1.
|
|
7
|
+
var SDK_VERSION = "1.8.1";
|
|
8
8
|
var DEFAULT_WIDGET_URL = "https://widget.flonk.id";
|
|
9
9
|
var DEFAULT_API_BASE = "https://api.flonk.id/v1";
|
|
10
10
|
var WIDGET_EVENTS = {
|
|
@@ -90,37 +90,69 @@ async function fetchWithTimeout(url, init = {}, timeoutMs = DEFAULT_FETCH_TIMEOU
|
|
|
90
90
|
clearTimeout(timer);
|
|
91
91
|
}
|
|
92
92
|
}
|
|
93
|
+
var widgetTokenInflight = /* @__PURE__ */ new Map();
|
|
93
94
|
async function fetchWidgetToken(pk, apiBase) {
|
|
94
|
-
const
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
95
|
+
const key = `${apiBase}|${pk}`;
|
|
96
|
+
const existing = widgetTokenInflight.get(key);
|
|
97
|
+
if (existing) return existing;
|
|
98
|
+
const promise = (async () => {
|
|
99
|
+
const res = await fetchWithTimeout(`${apiBase}/public/widget-token`, {
|
|
100
|
+
headers: { "x-kyc-pk": pk },
|
|
101
|
+
credentials: "include"
|
|
102
|
+
});
|
|
103
|
+
if (!res.ok) {
|
|
104
|
+
let message = `Widget token request failed (${res.status})`;
|
|
105
|
+
try {
|
|
106
|
+
const b = await res.json();
|
|
107
|
+
message = b.error || b.message || message;
|
|
108
|
+
} catch {
|
|
109
|
+
}
|
|
110
|
+
throw new Error(message);
|
|
104
111
|
}
|
|
105
|
-
|
|
106
|
-
}
|
|
107
|
-
|
|
112
|
+
return res.json();
|
|
113
|
+
})().finally(() => {
|
|
114
|
+
widgetTokenInflight.delete(key);
|
|
115
|
+
});
|
|
116
|
+
widgetTokenInflight.set(key, promise);
|
|
117
|
+
return promise;
|
|
108
118
|
}
|
|
109
|
-
|
|
119
|
+
var BRANDING_CACHE_TTL_MS = 5 * 60 * 1e3;
|
|
120
|
+
var brandingCache = /* @__PURE__ */ new Map();
|
|
121
|
+
function brandingCacheKey(opts) {
|
|
122
|
+
if (opts.pk) return `pk:${opts.pk}`;
|
|
123
|
+
if (opts.sessionId) return `sid:${opts.sessionId}`;
|
|
124
|
+
if (opts.clientId) return `cid:${opts.clientId}`;
|
|
125
|
+
return null;
|
|
126
|
+
}
|
|
127
|
+
async function requestDesignTokens(apiBase, opts) {
|
|
110
128
|
const params = [];
|
|
111
129
|
if (opts.sessionId) params.push(`sessionId=${encodeURIComponent(opts.sessionId)}`);
|
|
112
130
|
else if (opts.clientId) params.push(`clientId=${encodeURIComponent(opts.clientId)}`);
|
|
113
131
|
const url = `${apiBase}/public/design-tokens${params.length ? "?" + params.join("&") : ""}`;
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
132
|
+
const res = await fetchWithTimeout(
|
|
133
|
+
url,
|
|
134
|
+
{ headers: opts.pk ? { "x-kyc-pk": opts.pk } : {}, credentials: "omit" },
|
|
135
|
+
8e3
|
|
136
|
+
);
|
|
137
|
+
return res.ok ? res.json() : null;
|
|
138
|
+
}
|
|
139
|
+
async function fetchDesignTokens(apiBase, opts) {
|
|
140
|
+
const key = brandingCacheKey(opts);
|
|
141
|
+
if (!key) return null;
|
|
142
|
+
const now = Date.now();
|
|
143
|
+
const cached = brandingCache.get(key);
|
|
144
|
+
if (cached && cached.expiresAt > now) {
|
|
145
|
+
return cached.promise;
|
|
123
146
|
}
|
|
147
|
+
const promise = requestDesignTokens(apiBase, opts).catch(() => null);
|
|
148
|
+
brandingCache.set(key, { promise, expiresAt: now + BRANDING_CACHE_TTL_MS });
|
|
149
|
+
promise.then((tokens) => {
|
|
150
|
+
if (tokens == null) brandingCache.delete(key);
|
|
151
|
+
});
|
|
152
|
+
return promise;
|
|
153
|
+
}
|
|
154
|
+
function preloadDesignTokens(apiBase, opts) {
|
|
155
|
+
return fetchDesignTokens(apiBase, opts);
|
|
124
156
|
}
|
|
125
157
|
function validateServerUrl(url) {
|
|
126
158
|
if (url.startsWith("/")) return;
|
|
@@ -137,25 +169,35 @@ function validateServerUrl(url) {
|
|
|
137
169
|
throw new Error(`Invalid serverUrl: ${url}`);
|
|
138
170
|
}
|
|
139
171
|
}
|
|
172
|
+
var sessionCreateInflight = /* @__PURE__ */ new Map();
|
|
140
173
|
async function fetchSessionFromServer(serverUrl, clientMetadata, requestHeaders) {
|
|
141
174
|
validateServerUrl(serverUrl);
|
|
142
|
-
const
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
175
|
+
const key = `${serverUrl}|${JSON.stringify(clientMetadata ?? null)}`;
|
|
176
|
+
const existing = sessionCreateInflight.get(key);
|
|
177
|
+
if (existing) return existing;
|
|
178
|
+
const promise = (async () => {
|
|
179
|
+
const res = await fetchWithTimeout(serverUrl, {
|
|
180
|
+
method: "POST",
|
|
181
|
+
headers: { "Content-Type": "application/json", ...requestHeaders },
|
|
182
|
+
credentials: "include",
|
|
183
|
+
body: JSON.stringify({ clientMetadata })
|
|
184
|
+
});
|
|
185
|
+
if (!res.ok) {
|
|
186
|
+
let message = `Session request failed (${res.status})`;
|
|
187
|
+
try {
|
|
188
|
+
const body = await res.json();
|
|
189
|
+
if (body.error) message = body.error;
|
|
190
|
+
else if (body.message) message = body.message;
|
|
191
|
+
} catch {
|
|
192
|
+
}
|
|
193
|
+
throw new Error(message);
|
|
155
194
|
}
|
|
156
|
-
|
|
157
|
-
}
|
|
158
|
-
|
|
195
|
+
return res.json();
|
|
196
|
+
})().finally(() => {
|
|
197
|
+
sessionCreateInflight.delete(key);
|
|
198
|
+
});
|
|
199
|
+
sessionCreateInflight.set(key, promise);
|
|
200
|
+
return promise;
|
|
159
201
|
}
|
|
160
202
|
async function fetchPublicSession(apiBase, sessionId, embedToken) {
|
|
161
203
|
const res = await fetchWithTimeout(`${apiBase}/public/session/${sessionId}`, {
|
|
@@ -705,6 +747,26 @@ var FlonkKYC = class {
|
|
|
705
747
|
this.widgetUrl = (options.widgetUrl || DEFAULT_WIDGET_URL).replace(/\/$/, "");
|
|
706
748
|
this.apiBase = (options.apiBase || DEFAULT_API_BASE).replace(/\/$/, "");
|
|
707
749
|
}
|
|
750
|
+
/**
|
|
751
|
+
* Warm the project's branding (colors) ahead of time so the widget paints the
|
|
752
|
+
* brand color on the first frame, with no branding round-trip at click time.
|
|
753
|
+
*
|
|
754
|
+
* Call it early — on page mount, route enter, or hover of the "verify" button
|
|
755
|
+
* — well before `init()`. The result is cached (module-level, 5-min TTL) and
|
|
756
|
+
* every subsequent `init()`/`open()` for the same key reads from it. Safe to
|
|
757
|
+
* call repeatedly; concurrent calls dedupe. Never throws.
|
|
758
|
+
*
|
|
759
|
+
* @example
|
|
760
|
+
* // in a layout effect, long before the user clicks "Verify"
|
|
761
|
+
* FlonkKYC.preloadBranding({ publishableKey: 'pk_live_...' });
|
|
762
|
+
*/
|
|
763
|
+
static preloadBranding(opts) {
|
|
764
|
+
const apiBase = (opts.apiBase || DEFAULT_API_BASE).replace(/\/$/, "");
|
|
765
|
+
return preloadDesignTokens(apiBase, {
|
|
766
|
+
pk: opts.publishableKey,
|
|
767
|
+
sessionId: opts.sessionId
|
|
768
|
+
}).then(() => void 0);
|
|
769
|
+
}
|
|
708
770
|
// ── Public API ───────────────────────────────────────
|
|
709
771
|
/**
|
|
710
772
|
* Open the KYC verification widget.
|
|
@@ -972,6 +1034,11 @@ var FlonkKYC = class {
|
|
|
972
1034
|
if (session.mlAutoCaptureEnabled) params.mlAutoCaptureEnabled = "true";
|
|
973
1035
|
if (session.mlCropEnabled !== false) params.mlCropEnabled = "true";
|
|
974
1036
|
if (session.mlVerifyEnabled) params.mlVerifyEnabled = "true";
|
|
1037
|
+
if (session.vaultReuseEnabled) params.vaultReuseEnabled = "true";
|
|
1038
|
+
if (session.vaultReuseChallenge) params.vaultReuseChallenge = session.vaultReuseChallenge;
|
|
1039
|
+
if (session.faceAutoCapture) params.faceAutoCapture = JSON.stringify(session.faceAutoCapture);
|
|
1040
|
+
if (session.project) params.project = JSON.stringify(session.project);
|
|
1041
|
+
params.policyReady = "1";
|
|
975
1042
|
if (designTokens?.colors) {
|
|
976
1043
|
params.designTokens = JSON.stringify(designTokens);
|
|
977
1044
|
}
|
|
@@ -1077,6 +1144,10 @@ function FlonkKYCWidget({
|
|
|
1077
1144
|
const callbacksRef = react.useRef({ onSuccess, onError, onCancel, onReady });
|
|
1078
1145
|
callbacksRef.current = { onSuccess, onError, onCancel, onReady };
|
|
1079
1146
|
const sdk = react.useMemo(() => new FlonkKYC({ widgetUrl, apiBase }), [widgetUrl, apiBase]);
|
|
1147
|
+
react.useEffect(() => {
|
|
1148
|
+
if (!publishableKey && !sessionId) return;
|
|
1149
|
+
void FlonkKYC.preloadBranding({ publishableKey, sessionId, apiBase });
|
|
1150
|
+
}, [publishableKey, sessionId, apiBase]);
|
|
1080
1151
|
const generationRef = react.useRef(0);
|
|
1081
1152
|
react.useEffect(() => {
|
|
1082
1153
|
if (!autoOpen) return;
|
|
@@ -1119,9 +1190,20 @@ function FlonkKYCWidget({
|
|
|
1119
1190
|
}, [sdk, publishableKey, serverUrl, sessionId, embedToken, lang, overlayColor, allowManualUpload, autoOpen]);
|
|
1120
1191
|
return /* @__PURE__ */ jsxRuntime.jsx("div", { ref: mountRef });
|
|
1121
1192
|
}
|
|
1193
|
+
function FlonkKYCBrandingPreloader({
|
|
1194
|
+
publishableKey,
|
|
1195
|
+
sessionId,
|
|
1196
|
+
apiBase
|
|
1197
|
+
}) {
|
|
1198
|
+
react.useEffect(() => {
|
|
1199
|
+
void FlonkKYC.preloadBranding({ publishableKey, sessionId, apiBase });
|
|
1200
|
+
}, [publishableKey, sessionId, apiBase]);
|
|
1201
|
+
return null;
|
|
1202
|
+
}
|
|
1122
1203
|
|
|
1123
1204
|
exports.FlonkError = FlonkError;
|
|
1124
1205
|
exports.FlonkKYC = FlonkKYC;
|
|
1206
|
+
exports.FlonkKYCBrandingPreloader = FlonkKYCBrandingPreloader;
|
|
1125
1207
|
exports.FlonkKYCWidget = FlonkKYCWidget;
|
|
1126
1208
|
exports.FlonkValidationError = FlonkValidationError;
|
|
1127
1209
|
//# sourceMappingURL=index.cjs.map
|