@flonkid/kyc 1.8.0 → 1.8.2

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 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.8.0";
7
+ var SDK_VERSION = "1.8.2";
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,21 +90,31 @@ 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 res = await fetchWithTimeout(`${apiBase}/public/widget-token`, {
95
- headers: { "x-kyc-pk": pk },
96
- credentials: "include"
97
- });
98
- if (!res.ok) {
99
- let message = `Widget token request failed (${res.status})`;
100
- try {
101
- const b = await res.json();
102
- message = b.error || b.message || message;
103
- } catch {
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
- throw new Error(message);
106
- }
107
- return res.json();
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;
110
120
  var brandingCache = /* @__PURE__ */ new Map();
@@ -159,43 +169,35 @@ function validateServerUrl(url) {
159
169
  throw new Error(`Invalid serverUrl: ${url}`);
160
170
  }
161
171
  }
172
+ var sessionCreateInflight = /* @__PURE__ */ new Map();
162
173
  async function fetchSessionFromServer(serverUrl, clientMetadata, requestHeaders) {
163
174
  validateServerUrl(serverUrl);
164
- const res = await fetchWithTimeout(serverUrl, {
165
- method: "POST",
166
- headers: { "Content-Type": "application/json", ...requestHeaders },
167
- credentials: "include",
168
- body: JSON.stringify({ clientMetadata })
169
- });
170
- if (!res.ok) {
171
- let message = `Session request failed (${res.status})`;
172
- try {
173
- const body = await res.json();
174
- if (body.error) message = body.error;
175
- else if (body.message) message = body.message;
176
- } catch {
177
- }
178
- throw new Error(message);
179
- }
180
- return res.json();
181
- }
182
- async function fetchPublicSession(apiBase, sessionId, embedToken) {
183
- const res = await fetchWithTimeout(`${apiBase}/public/session/${sessionId}`, {
184
- headers: {
185
- "Content-Type": "application/json",
186
- "Authorization": `Bearer ${embedToken}`
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);
187
194
  }
195
+ return res.json();
196
+ })().finally(() => {
197
+ sessionCreateInflight.delete(key);
188
198
  });
189
- if (!res.ok) {
190
- let message = `Failed to fetch session (${res.status})`;
191
- try {
192
- const b = await res.json();
193
- message = b.error || b.message || message;
194
- } catch {
195
- }
196
- throw new Error(message);
197
- }
198
- return res.json();
199
+ sessionCreateInflight.set(key, promise);
200
+ return promise;
199
201
  }
200
202
  async function exchangeSessionForToken(apiBase, sessionId) {
201
203
  const res = await fetchWithTimeout(`${apiBase}/public/session/${sessionId}/token`, {
@@ -876,20 +878,7 @@ var FlonkKYC = class {
876
878
  const finalTokens = designTokens ?? await fetchDesignTokens(this.apiBase, { sessionId });
877
879
  const finalColor = primaryFrom(finalTokens);
878
880
  if (finalColor !== primaryColor) loader.updateColor(finalColor);
879
- const sessionData = await fetchPublicSession(this.apiBase, sessionId, embedToken);
880
- const session = {
881
- id: sessionData.id,
882
- allowManualUpload: sessionData.allowManualUpload ?? config.allowManualUpload ?? true,
883
- clientMetadata: sessionData.clientMetadata || config.clientMetadata,
884
- qrCodeUrl: sessionData.qrCodeUrl,
885
- testMode: sessionData.testMode || false,
886
- poaEnabled: sessionData.poaEnabled || false,
887
- poaRequired: sessionData.poaRequired || false,
888
- mlAutoCaptureEnabled: sessionData.mlAutoCaptureEnabled || false,
889
- mlCropEnabled: sessionData.mlCropEnabled ?? true,
890
- mlVerifyEnabled: sessionData.mlVerifyEnabled || false
891
- };
892
- return this.buildWidget(embedToken, session, config, loader, finalTokens);
881
+ return this.buildWidget(embedToken, sessionId, config, loader, finalTokens);
893
882
  } catch (err) {
894
883
  const msg = err.message || "Failed to create session";
895
884
  loader.showError(msg, config.lang);
@@ -903,32 +892,12 @@ var FlonkKYC = class {
903
892
  async initWithEmbedToken(config) {
904
893
  const pk = config.publishableKey;
905
894
  const designTokensPromise = pk ? fetchDesignTokens(this.apiBase, { pk }) : fetchDesignTokens(this.apiBase, { sessionId: config.sessionId });
906
- const sessionPromise = fetchPublicSession(
907
- this.apiBase,
908
- config.sessionId,
909
- config.embedToken
910
- );
911
895
  const { loader, primaryColor } = await showLoaderWithEarlyColor(designTokensPromise, config.lang);
912
896
  try {
913
- const [sessionData, designTokens] = await Promise.all([
914
- sessionPromise,
915
- designTokensPromise
916
- ]);
897
+ const designTokens = await designTokensPromise;
917
898
  const finalColor = primaryFrom(designTokens);
918
899
  if (finalColor !== primaryColor) loader.updateColor(finalColor);
919
- const session = {
920
- id: sessionData.id,
921
- allowManualUpload: sessionData.allowManualUpload ?? config.allowManualUpload ?? true,
922
- clientMetadata: sessionData.clientMetadata || config.clientMetadata,
923
- qrCodeUrl: sessionData.qrCodeUrl,
924
- testMode: sessionData.testMode || false,
925
- poaEnabled: sessionData.poaEnabled || false,
926
- poaRequired: sessionData.poaRequired || false,
927
- mlAutoCaptureEnabled: sessionData.mlAutoCaptureEnabled || false,
928
- mlCropEnabled: sessionData.mlCropEnabled ?? true,
929
- mlVerifyEnabled: sessionData.mlVerifyEnabled || false
930
- };
931
- return this.buildWidget(config.embedToken, session, config, loader, designTokens);
900
+ return this.buildWidget(config.embedToken, config.sessionId, config, loader, designTokens);
932
901
  } catch (err) {
933
902
  const msg = err.message || "Failed to initialize verification";
934
903
  loader.showError(msg, config.lang);
@@ -954,7 +923,7 @@ var FlonkKYC = class {
954
923
  exchangePromise,
955
924
  designTokensPromise
956
925
  ]);
957
- return this.buildWidget(embedToken, session, config, loader, designTokens);
926
+ return this.buildWidget(embedToken, config.sessionId || session.id, config, loader, designTokens);
958
927
  } catch (err) {
959
928
  const msg = err.message || "Failed to initialize verification";
960
929
  loader.showError(msg, config.lang);
@@ -1001,27 +970,21 @@ var FlonkKYC = class {
1001
970
  }
1002
971
  }
1003
972
  // ── Core widget builder ──────────────────────────────
1004
- buildWidget(token, session, config, loader, designTokens) {
973
+ buildWidget(token, sessionId, config, loader, designTokens) {
1005
974
  const params = {
1006
975
  mode: "embedded",
1007
- sessionId: config.sessionId || session.id,
1008
- token,
1009
- allowManualUpload: String(session.allowManualUpload !== false)
976
+ sessionId,
977
+ token
1010
978
  };
1011
- if (session.testMode) params.testMode = "true";
1012
- if (session.poaEnabled) params.poaEnabled = "true";
1013
- if (session.poaRequired) params.poaRequired = "true";
1014
- if (session.mlAutoCaptureEnabled) params.mlAutoCaptureEnabled = "true";
1015
- if (session.mlCropEnabled !== false) params.mlCropEnabled = "true";
1016
- if (session.mlVerifyEnabled) params.mlVerifyEnabled = "true";
979
+ if (config.allowManualUpload !== void 0) {
980
+ params.allowManualUpload = String(config.allowManualUpload !== false);
981
+ }
1017
982
  if (designTokens?.colors) {
1018
983
  params.designTokens = JSON.stringify(designTokens);
1019
984
  }
1020
985
  if (config.embedToken) params.embedToken = config.embedToken;
1021
- if (session.qrCodeUrl) params.qrCodeUrl = session.qrCodeUrl;
1022
- const clientMetadata = session.clientMetadata || config.clientMetadata;
1023
- if (clientMetadata) {
1024
- params.clientMetadata = JSON.stringify(clientMetadata);
986
+ if (config.clientMetadata) {
987
+ params.clientMetadata = JSON.stringify(config.clientMetadata);
1025
988
  }
1026
989
  if (config.lang) params.lang = config.lang;
1027
990
  if (config.overlayColor) params.overlayColor = config.overlayColor;