vesant-sdk 1.7.1-dev.afc5a32 → 1.7.1-dev.c2ac5a5
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 +4 -0
- package/dist/{client-D23KhWeh.d.mts → client-5q4whhGu.d.mts} +1 -1
- package/dist/{client-fy3trF2K.d.ts → client-BaUekQT8.d.ts} +32 -10
- package/dist/{client-B3DCAHlg.d.ts → client-DUHC-68_.d.ts} +1 -1
- package/dist/{client-BwXMQA2a.d.mts → client-XDEhh9VN.d.mts} +32 -10
- package/dist/compliance/index.d.mts +2 -2
- package/dist/compliance/index.d.ts +2 -2
- package/dist/compliance/index.js +39 -1
- package/dist/compliance/index.js.map +1 -1
- package/dist/compliance/index.mjs +39 -1
- package/dist/compliance/index.mjs.map +1 -1
- package/dist/geolocation/index.d.mts +2 -2
- package/dist/geolocation/index.d.ts +2 -2
- package/dist/geolocation/index.js +39 -1
- package/dist/geolocation/index.js.map +1 -1
- package/dist/geolocation/index.mjs +39 -1
- package/dist/geolocation/index.mjs.map +1 -1
- package/dist/index.d.mts +3 -3
- package/dist/index.d.ts +3 -3
- package/dist/index.js +86 -23
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +86 -23
- package/dist/index.mjs.map +1 -1
- package/dist/kyc/core.d.mts +1 -1
- package/dist/kyc/core.d.ts +1 -1
- package/dist/kyc/core.js +47 -22
- package/dist/kyc/core.js.map +1 -1
- package/dist/kyc/core.mjs +47 -22
- package/dist/kyc/core.mjs.map +1 -1
- package/dist/kyc/index.d.mts +178 -39
- package/dist/kyc/index.d.ts +178 -39
- package/dist/kyc/index.js +47 -22
- package/dist/kyc/index.js.map +1 -1
- package/dist/kyc/index.mjs +47 -22
- package/dist/kyc/index.mjs.map +1 -1
- package/dist/react.d.mts +126 -48
- package/dist/react.d.ts +126 -48
- package/dist/react.js +131 -20
- package/dist/react.js.map +1 -1
- package/dist/react.mjs +129 -21
- package/dist/react.mjs.map +1 -1
- package/package.json +1 -1
package/dist/react.js
CHANGED
|
@@ -429,14 +429,11 @@ function useCipherText(client) {
|
|
|
429
429
|
const [configLoading, setConfigLoading] = React.useState(!!client);
|
|
430
430
|
const [configError, setConfigError] = React.useState(null);
|
|
431
431
|
const configRef = React.useRef(void 0);
|
|
432
|
-
const configPromiseRef = React.useRef(null);
|
|
433
432
|
React.useEffect(() => {
|
|
434
433
|
if (!client) return;
|
|
435
434
|
let cancelled = false;
|
|
436
435
|
setConfigLoading(true);
|
|
437
|
-
|
|
438
|
-
configPromiseRef.current = promise;
|
|
439
|
-
promise.then((cfg) => {
|
|
436
|
+
client.getGPSConfig().then((cfg) => {
|
|
440
437
|
if (!cancelled) {
|
|
441
438
|
configRef.current = cfg;
|
|
442
439
|
setConfigLoading(false);
|
|
@@ -451,13 +448,21 @@ function useCipherText(client) {
|
|
|
451
448
|
cancelled = true;
|
|
452
449
|
};
|
|
453
450
|
}, [client]);
|
|
451
|
+
const refreshConfig = React.useCallback(async () => {
|
|
452
|
+
if (!client) return;
|
|
453
|
+
try {
|
|
454
|
+
configRef.current = await client.refreshGPSConfig();
|
|
455
|
+
setConfigError(null);
|
|
456
|
+
} catch (error) {
|
|
457
|
+
setConfigError(error instanceof Error ? error : new Error("Failed to refresh GPS config"));
|
|
458
|
+
}
|
|
459
|
+
}, [client]);
|
|
454
460
|
const generate = React.useCallback(
|
|
455
461
|
async (options) => {
|
|
456
462
|
try {
|
|
457
|
-
if (
|
|
463
|
+
if (client) {
|
|
458
464
|
try {
|
|
459
|
-
|
|
460
|
-
configRef.current = cfg;
|
|
465
|
+
configRef.current = await client.getGPSConfig();
|
|
461
466
|
} catch {
|
|
462
467
|
}
|
|
463
468
|
}
|
|
@@ -467,9 +472,9 @@ function useCipherText(client) {
|
|
|
467
472
|
return null;
|
|
468
473
|
}
|
|
469
474
|
},
|
|
470
|
-
[]
|
|
475
|
+
[client]
|
|
471
476
|
);
|
|
472
|
-
return { generate, configLoading, configError };
|
|
477
|
+
return { generate, refreshConfig, configLoading, configError };
|
|
473
478
|
}
|
|
474
479
|
function useLocationRequests(client, options = {}) {
|
|
475
480
|
const [requests, setRequests] = React.useState([]);
|
|
@@ -1009,6 +1014,46 @@ function loadMediaPipeFaceDetection(assetBasePath) {
|
|
|
1009
1014
|
|
|
1010
1015
|
// src/kyc/hostedJourney.ts
|
|
1011
1016
|
var REUSE_KYC_SESSION_EXPIRY_MS = 10 * 60 * 1e3;
|
|
1017
|
+
var JOURNEY_FRAME_HEIGHT = "clamp(500px, 64vh, 680px)";
|
|
1018
|
+
var JOURNEY_CONFIRM_TIMEOUT_MS = 45e3;
|
|
1019
|
+
function journeyOutcomeFromMessage(data) {
|
|
1020
|
+
const status = data?.verification_status;
|
|
1021
|
+
if (typeof status !== "string") return null;
|
|
1022
|
+
switch (status) {
|
|
1023
|
+
case "verification.accepted":
|
|
1024
|
+
return "accepted";
|
|
1025
|
+
case "verification.declined":
|
|
1026
|
+
return "declined";
|
|
1027
|
+
case "verification.cancelled":
|
|
1028
|
+
case "request.timeout":
|
|
1029
|
+
case "request.invalid":
|
|
1030
|
+
case "request.unauthorized":
|
|
1031
|
+
case "request.deleted":
|
|
1032
|
+
return "cancelled";
|
|
1033
|
+
default:
|
|
1034
|
+
return null;
|
|
1035
|
+
}
|
|
1036
|
+
}
|
|
1037
|
+
function journeyPollIntervalMs(confirming) {
|
|
1038
|
+
return confirming ? 1e3 : 2500;
|
|
1039
|
+
}
|
|
1040
|
+
function pendingJourneyResult(reference) {
|
|
1041
|
+
return {
|
|
1042
|
+
event: "reuse_kyc",
|
|
1043
|
+
reference,
|
|
1044
|
+
resource_id: "",
|
|
1045
|
+
status: "pending",
|
|
1046
|
+
data: {
|
|
1047
|
+
retries_remaining: 0,
|
|
1048
|
+
retry_limit_exceeded: false,
|
|
1049
|
+
trigger_alert: false,
|
|
1050
|
+
enforce_logout: false,
|
|
1051
|
+
freeze_account: false,
|
|
1052
|
+
block: false,
|
|
1053
|
+
freeze_duration_minutes: 0
|
|
1054
|
+
}
|
|
1055
|
+
};
|
|
1056
|
+
}
|
|
1012
1057
|
function tryStartOperation(guard) {
|
|
1013
1058
|
if (guard.current) return false;
|
|
1014
1059
|
guard.current = true;
|
|
@@ -1020,12 +1065,22 @@ function releaseOperation(guard) {
|
|
|
1020
1065
|
function retryTarget(hasHostedJourney) {
|
|
1021
1066
|
return hasHostedJourney ? "journey" : "capture";
|
|
1022
1067
|
}
|
|
1068
|
+
var CAPTURE_MODAL_MAX_WIDTH = 448;
|
|
1023
1069
|
function modalMaxWidth(hasHostedJourney) {
|
|
1024
|
-
return hasHostedJourney ?
|
|
1070
|
+
return hasHostedJourney ? CAPTURE_MODAL_MAX_WIDTH : CAPTURE_MODAL_MAX_WIDTH;
|
|
1071
|
+
}
|
|
1072
|
+
var JOURNEY_CONTENT_PADDING = 12;
|
|
1073
|
+
function resultForModalClose(stageKind, result, unconfirmed) {
|
|
1074
|
+
const terminal = stageKind === "accepted" || stageKind === "declined" || stageKind === "max_attempts";
|
|
1075
|
+
if (terminal && result !== void 0) return result;
|
|
1076
|
+
const awaitingConfirmation = stageKind === "confirming" || stageKind === "unconfirmed";
|
|
1077
|
+
if (awaitingConfirmation && unconfirmed !== void 0) return unconfirmed;
|
|
1078
|
+
return null;
|
|
1025
1079
|
}
|
|
1026
1080
|
|
|
1027
1081
|
// src/kyc/FaceCaptureModal.tsx
|
|
1028
1082
|
var MOBILE_UA = /Mobi|Android|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i;
|
|
1083
|
+
var ACCEPTED_AUTO_CLOSE_MS = 1200;
|
|
1029
1084
|
var LIVENESS_MESSAGES = [
|
|
1030
1085
|
"Position your face inside the oval",
|
|
1031
1086
|
"Make sure your face is well lit",
|
|
@@ -1038,6 +1093,10 @@ function headerSubtitle(stageKind) {
|
|
|
1038
1093
|
return "Use your phone to continue";
|
|
1039
1094
|
case "journey":
|
|
1040
1095
|
return "Follow the steps to verify your identity";
|
|
1096
|
+
case "confirming":
|
|
1097
|
+
return "Confirming your result";
|
|
1098
|
+
case "unconfirmed":
|
|
1099
|
+
return "Still confirming";
|
|
1041
1100
|
case "accepted":
|
|
1042
1101
|
return "All set";
|
|
1043
1102
|
case "declined":
|
|
@@ -1137,8 +1196,10 @@ function FaceCaptureModal({
|
|
|
1137
1196
|
stopped = true;
|
|
1138
1197
|
};
|
|
1139
1198
|
}, [stage.kind, stage.kind === "qr" ? stage.mobileConnected : false]);
|
|
1199
|
+
const journeyUrl = stage.kind === "journey" || stage.kind === "confirming" ? stage.url : "";
|
|
1140
1200
|
React.useEffect(() => {
|
|
1141
|
-
if (stage.kind !== "journey" || !
|
|
1201
|
+
if (stage.kind !== "journey" && stage.kind !== "confirming" || !journeyUrl) return;
|
|
1202
|
+
const intervalMs = journeyPollIntervalMs(stage.kind === "confirming");
|
|
1142
1203
|
let stopped = false;
|
|
1143
1204
|
const checkOnce = async () => {
|
|
1144
1205
|
try {
|
|
@@ -1155,27 +1216,43 @@ function FaceCaptureModal({
|
|
|
1155
1216
|
if (stopped || cancelledRef.current) return;
|
|
1156
1217
|
await checkOnce();
|
|
1157
1218
|
if (!stopped && !cancelledRef.current) {
|
|
1158
|
-
setTimeout(tick,
|
|
1219
|
+
setTimeout(tick, intervalMs);
|
|
1159
1220
|
}
|
|
1160
1221
|
};
|
|
1161
1222
|
void tick();
|
|
1162
1223
|
let frameOrigin = "";
|
|
1163
1224
|
try {
|
|
1164
|
-
frameOrigin = new URL(
|
|
1225
|
+
frameOrigin = new URL(journeyUrl).origin;
|
|
1165
1226
|
} catch {
|
|
1166
1227
|
frameOrigin = "";
|
|
1167
1228
|
}
|
|
1168
1229
|
const onMessage = (e) => {
|
|
1169
1230
|
if (!frameOrigin || e.origin !== frameOrigin) return;
|
|
1170
|
-
const
|
|
1171
|
-
if (
|
|
1231
|
+
const outcome = journeyOutcomeFromMessage(e.data);
|
|
1232
|
+
if (!outcome) return;
|
|
1233
|
+
void checkOnce();
|
|
1234
|
+
setStage((prev) => {
|
|
1235
|
+
if (prev.kind !== "journey") return prev;
|
|
1236
|
+
if (outcome === "cancelled") {
|
|
1237
|
+
return { kind: "error", message: "The verification was closed before it finished. Please try again." };
|
|
1238
|
+
}
|
|
1239
|
+
return { kind: "confirming", outcome, url: prev.url };
|
|
1240
|
+
});
|
|
1172
1241
|
};
|
|
1173
1242
|
window.addEventListener("message", onMessage);
|
|
1174
1243
|
return () => {
|
|
1175
1244
|
stopped = true;
|
|
1176
1245
|
window.removeEventListener("message", onMessage);
|
|
1177
1246
|
};
|
|
1178
|
-
}, [stage.kind,
|
|
1247
|
+
}, [stage.kind, journeyUrl]);
|
|
1248
|
+
React.useEffect(() => {
|
|
1249
|
+
if (stage.kind !== "confirming") return;
|
|
1250
|
+
const outcome = stage.outcome;
|
|
1251
|
+
const timer = setTimeout(() => {
|
|
1252
|
+
setStage((prev) => prev.kind === "confirming" ? { kind: "unconfirmed", outcome } : prev);
|
|
1253
|
+
}, JOURNEY_CONFIRM_TIMEOUT_MS);
|
|
1254
|
+
return () => clearTimeout(timer);
|
|
1255
|
+
}, [stage.kind, stage.kind === "confirming" ? stage.outcome : ""]);
|
|
1179
1256
|
const handleJourneyRetry = async () => {
|
|
1180
1257
|
if (!tryStartOperation(journeyRetryingRef)) return;
|
|
1181
1258
|
setStage({ kind: "journey", url: "" });
|
|
@@ -1322,12 +1399,23 @@ function FaceCaptureModal({
|
|
|
1322
1399
|
}, 3e3);
|
|
1323
1400
|
return () => clearInterval(interval);
|
|
1324
1401
|
}, [captureMode]);
|
|
1325
|
-
const close = (result) => {
|
|
1402
|
+
const close = React.useCallback((result) => {
|
|
1326
1403
|
cancelledRef.current = true;
|
|
1327
1404
|
if (result === null && onCancel) {
|
|
1328
1405
|
onCancel();
|
|
1329
1406
|
}
|
|
1330
1407
|
onComplete(result);
|
|
1408
|
+
}, [onCancel, onComplete]);
|
|
1409
|
+
React.useEffect(() => {
|
|
1410
|
+
if (stage.kind !== "accepted") return;
|
|
1411
|
+
const result = stage.result;
|
|
1412
|
+
const timer = setTimeout(() => close(result), ACCEPTED_AUTO_CLOSE_MS);
|
|
1413
|
+
return () => clearTimeout(timer);
|
|
1414
|
+
}, [close, stage]);
|
|
1415
|
+
const handleHeaderClose = () => {
|
|
1416
|
+
const result = "result" in stage ? stage.result : void 0;
|
|
1417
|
+
const unconfirmed = stage.kind === "confirming" || stage.kind === "unconfirmed" ? pendingJourneyResult(session.reference) : void 0;
|
|
1418
|
+
close(resultForModalClose(stage.kind, result, unconfirmed));
|
|
1331
1419
|
};
|
|
1332
1420
|
const renderChoose = () => /* @__PURE__ */ React__default.default.createElement("div", { style: contentStyle }, /* @__PURE__ */ React__default.default.createElement("div", { style: visualGuideContainerStyle }, /* @__PURE__ */ React__default.default.createElement("div", { style: visualGuideStyle }, /* @__PURE__ */ React__default.default.createElement("div", { style: circleStyle }, /* @__PURE__ */ React__default.default.createElement("img", { src: Camera, alt: "", width: 48, height: 48 })))), /* @__PURE__ */ React__default.default.createElement("p", { style: subtitleStyle }, "How would you like to verify?"), /* @__PURE__ */ React__default.default.createElement("div", { style: buttonsContainerStyle }, /* @__PURE__ */ React__default.default.createElement(
|
|
1333
1421
|
"button",
|
|
@@ -1399,7 +1487,16 @@ function FaceCaptureModal({
|
|
|
1399
1487
|
"Try Again"
|
|
1400
1488
|
), /* @__PURE__ */ React__default.default.createElement("button", { style: cancelButtonStyle, onClick: () => close(null) }, sessionExpired ? "Close" : "Cancel")));
|
|
1401
1489
|
};
|
|
1402
|
-
const
|
|
1490
|
+
const renderConfirming = () => /* @__PURE__ */ React__default.default.createElement("div", { style: { ...contentStyle, alignItems: "center", textAlign: "center" } }, /* @__PURE__ */ React__default.default.createElement("div", { style: { ...spinnerStyle, margin: "24px auto", width: 32, height: 32 } }), /* @__PURE__ */ React__default.default.createElement("h3", { style: titleStyle }, "Confirming your result\u2026"), /* @__PURE__ */ React__default.default.createElement("p", { style: { ...attemptsTextStyle, marginTop: 8 } }, "This usually takes a few seconds."));
|
|
1491
|
+
const renderUnconfirmed = (outcome) => /* @__PURE__ */ React__default.default.createElement("div", { style: { ...contentStyle, alignItems: "center", textAlign: "center" } }, /* @__PURE__ */ React__default.default.createElement("div", { style: errorCircleStyle }, "!"), /* @__PURE__ */ React__default.default.createElement("h3", { style: titleStyle }, "Still confirming"), /* @__PURE__ */ React__default.default.createElement("p", { style: alertTextStyle }, outcome === "accepted" ? "Your verification was submitted, but we haven't received the final result yet. You can close this window and we'll keep checking in the background." : "Your last attempt wasn't accepted, but we haven't received the details yet. You can try again or close this window."), /* @__PURE__ */ React__default.default.createElement("div", { style: buttonsContainerStyle }, outcome === "declined" && /* @__PURE__ */ React__default.default.createElement("button", { style: primaryButtonStyle, onClick: () => void handleJourneyRetry() }, "Try Again"), /* @__PURE__ */ React__default.default.createElement(
|
|
1492
|
+
"button",
|
|
1493
|
+
{
|
|
1494
|
+
style: outcome === "accepted" ? primaryButtonStyle : cancelButtonStyle,
|
|
1495
|
+
onClick: () => close(pendingJourneyResult(session.reference))
|
|
1496
|
+
},
|
|
1497
|
+
"Close"
|
|
1498
|
+
)));
|
|
1499
|
+
const renderJourney = (url) => /* @__PURE__ */ React__default.default.createElement("div", { style: { ...contentStyle, padding: JOURNEY_CONTENT_PADDING } }, url ? /* @__PURE__ */ React__default.default.createElement(
|
|
1403
1500
|
"iframe",
|
|
1404
1501
|
{
|
|
1405
1502
|
src: url,
|
|
@@ -1418,6 +1515,10 @@ function FaceCaptureModal({
|
|
|
1418
1515
|
return renderCapture(stage.declinedReason);
|
|
1419
1516
|
case "journey":
|
|
1420
1517
|
return renderJourney(stage.url);
|
|
1518
|
+
case "confirming":
|
|
1519
|
+
return renderConfirming();
|
|
1520
|
+
case "unconfirmed":
|
|
1521
|
+
return renderUnconfirmed(stage.outcome);
|
|
1421
1522
|
case "submitting":
|
|
1422
1523
|
return renderSubmitting();
|
|
1423
1524
|
case "accepted":
|
|
@@ -1433,7 +1534,7 @@ function FaceCaptureModal({
|
|
|
1433
1534
|
return /* @__PURE__ */ React__default.default.createElement(React__default.default.Fragment, null, /* @__PURE__ */ React__default.default.createElement("style", null, keyframes), /* @__PURE__ */ React__default.default.createElement("div", { style: overlayStyle }, /* @__PURE__ */ React__default.default.createElement("div", { style: { ...modalStyle, maxWidth: modalMaxWidth(journeyMode) } }, /* @__PURE__ */ React__default.default.createElement("div", { style: headerStyle }, /* @__PURE__ */ React__default.default.createElement(
|
|
1434
1535
|
"button",
|
|
1435
1536
|
{
|
|
1436
|
-
onClick:
|
|
1537
|
+
onClick: handleHeaderClose,
|
|
1437
1538
|
style: closeButtonStyle,
|
|
1438
1539
|
"aria-label": "Close"
|
|
1439
1540
|
},
|
|
@@ -1492,7 +1593,7 @@ var contentStyle = {
|
|
|
1492
1593
|
};
|
|
1493
1594
|
var journeyFrameStyle = {
|
|
1494
1595
|
width: "100%",
|
|
1495
|
-
height:
|
|
1596
|
+
height: JOURNEY_FRAME_HEIGHT,
|
|
1496
1597
|
border: 0,
|
|
1497
1598
|
borderRadius: 12,
|
|
1498
1599
|
background: "#f9fafb"
|
|
@@ -2279,6 +2380,13 @@ function getRiskColor(risk) {
|
|
|
2279
2380
|
};
|
|
2280
2381
|
return colorMap[risk] || "#6b7280";
|
|
2281
2382
|
}
|
|
2383
|
+
function isMobileDevice(userAgent) {
|
|
2384
|
+
const ua = userAgent ?? (typeof navigator === "undefined" ? "" : navigator.userAgent);
|
|
2385
|
+
return /Mobi|Android|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(ua);
|
|
2386
|
+
}
|
|
2387
|
+
function buildEventBasedFaceVerificationQrPayload(token) {
|
|
2388
|
+
return `vesant://reuse-kyc?token=${encodeURIComponent(token)}`;
|
|
2389
|
+
}
|
|
2282
2390
|
function useEventBasedFaceVerificationSubmission(client$1) {
|
|
2283
2391
|
const startSession = React.useCallback(
|
|
2284
2392
|
(request) => client$1.createEventBasedFaceVerificationSession(request),
|
|
@@ -2326,12 +2434,15 @@ function useEventBasedFaceVerificationSubmission(client$1) {
|
|
|
2326
2434
|
return { startSession, verifyFace, runFlow };
|
|
2327
2435
|
}
|
|
2328
2436
|
|
|
2437
|
+
exports.FaceCaptureModal = FaceCaptureModal_default;
|
|
2438
|
+
exports.buildEventBasedFaceVerificationQrPayload = buildEventBasedFaceVerificationQrPayload;
|
|
2329
2439
|
exports.createDeviceFingerprint = createDeviceFingerprint;
|
|
2330
2440
|
exports.fileToBase64 = fileToBase64;
|
|
2331
2441
|
exports.formatKycStatus = formatKycStatus;
|
|
2332
2442
|
exports.getBrowserInfo = getBrowserInfo;
|
|
2333
2443
|
exports.getRiskColor = getRiskColor;
|
|
2334
2444
|
exports.getStatusColor = getStatusColor;
|
|
2445
|
+
exports.isMobileDevice = isMobileDevice;
|
|
2335
2446
|
exports.isValidFileSize = isValidFileSize;
|
|
2336
2447
|
exports.isValidFileType = isValidFileType;
|
|
2337
2448
|
exports.useCipherText = useCipherText;
|