astra-sdk-web 1.1.7 → 1.1.9

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.
@@ -219,6 +219,12 @@ function mergeConfig(userConfig) {
219
219
  }
220
220
 
221
221
  // src/services/kycApiService.ts
222
+ var COMPLETED_STEPS = {
223
+ INITIATED: "initiated",
224
+ FACE: "face_scan",
225
+ DOCS: "document_upload",
226
+ COMPLETED: "completed"
227
+ };
222
228
  var KycApiService = class {
223
229
  config;
224
230
  constructor(config) {
@@ -641,7 +647,17 @@ function DocumentUploadModal({ onComplete }) {
641
647
  const checkSession = async () => {
642
648
  if (!apiService) return;
643
649
  try {
644
- await apiService.checkSessionActive();
650
+ const statusResponse = await apiService.getSessionStatus();
651
+ const { completed_steps, next_step, status } = statusResponse.data;
652
+ if (status !== "ACTIVE") {
653
+ throw new Error("Session expired or inactive");
654
+ }
655
+ if (completed_steps.includes(COMPLETED_STEPS.DOCS)) {
656
+ console.log("Document already uploaded");
657
+ }
658
+ if (next_step === COMPLETED_STEPS.FACE && !completed_steps.includes(COMPLETED_STEPS.FACE)) {
659
+ console.warn("Face scan not completed, but in document upload modal");
660
+ }
645
661
  setSessionError(null);
646
662
  } catch (error) {
647
663
  const message = error.message || "Session expired or inactive";
@@ -954,6 +970,8 @@ var FaceMeshService = class {
954
970
  }
955
971
  this.processLiveness(faceOnCanvas, w, h);
956
972
  } else {
973
+ this.livenessStateRef.current.currentYaw = null;
974
+ this.livenessStateRef.current.currentAbsYaw = null;
957
975
  const vid = this.videoRef.current;
958
976
  if (vid) {
959
977
  const vidW = Math.max(1, vid?.videoWidth || displayW);
@@ -997,6 +1015,8 @@ var FaceMeshService = class {
997
1015
  const midX = (leftEyeOuter.x + rightEyeOuter.x) / 2;
998
1016
  const yaw = (nT.x - midX) / Math.max(1e-6, faceWidth);
999
1017
  const absYaw = Math.abs(yaw);
1018
+ this.livenessStateRef.current.currentYaw = yaw;
1019
+ this.livenessStateRef.current.currentAbsYaw = absYaw;
1000
1020
  const xs = faceOnCanvas.map((p) => p.x), ys = faceOnCanvas.map((p) => p.y);
1001
1021
  const minX = Math.min(...xs) * w, maxX = Math.max(...xs) * w;
1002
1022
  const minY = Math.min(...ys) * h, maxY = Math.max(...ys) * h;
@@ -1023,11 +1043,13 @@ var FaceMeshService = class {
1023
1043
  } else if (absYaw < centerThreshold) {
1024
1044
  state.centerHold += 1;
1025
1045
  if (state.centerHold >= holdFramesCenter) {
1026
- const newStage = "LEFT";
1027
- state.stage = newStage;
1028
- state.centerHold = 0;
1029
- if (this.callbacks.onLivenessUpdate) {
1030
- this.callbacks.onLivenessUpdate(newStage, "Turn your face LEFT");
1046
+ if (!state.livenessCompleted) {
1047
+ const newStage = "LEFT";
1048
+ state.stage = newStage;
1049
+ state.centerHold = 0;
1050
+ if (this.callbacks.onLivenessUpdate) {
1051
+ this.callbacks.onLivenessUpdate(newStage, "Turn your face LEFT");
1052
+ }
1031
1053
  }
1032
1054
  }
1033
1055
  } else {
@@ -1066,16 +1088,12 @@ var FaceMeshService = class {
1066
1088
  state.rightHold += 1;
1067
1089
  if (state.rightHold >= holdFramesTurn) {
1068
1090
  state.rightHold = 0;
1069
- if (!state.snapTriggered) {
1070
- state.snapTriggered = true;
1071
- const newStage = "DONE";
1072
- state.stage = newStage;
1073
- if (this.callbacks.onLivenessUpdate) {
1074
- this.callbacks.onLivenessUpdate(newStage, "Capturing...");
1075
- }
1076
- if (this.callbacks.onCaptureTrigger) {
1077
- this.callbacks.onCaptureTrigger();
1078
- }
1091
+ state.livenessCompleted = true;
1092
+ const newStage = "DONE";
1093
+ state.stage = newStage;
1094
+ state.centerHold = 0;
1095
+ if (this.callbacks.onLivenessUpdate) {
1096
+ this.callbacks.onLivenessUpdate(newStage, "Great! Now look straight at the camera");
1079
1097
  }
1080
1098
  }
1081
1099
  } else {
@@ -1084,6 +1102,25 @@ var FaceMeshService = class {
1084
1102
  this.callbacks.onLivenessUpdate(state.stage, yaw < -0.08 ? "You're facing left. Turn RIGHT" : "Turn a bit more RIGHT");
1085
1103
  }
1086
1104
  }
1105
+ } else if (state.stage === "DONE") {
1106
+ const reducedThreshold = 0.08;
1107
+ if (absYaw < reducedThreshold) {
1108
+ state.centerHold += 1;
1109
+ if (state.centerHold >= holdFramesCenter && !state.snapTriggered) {
1110
+ state.snapTriggered = true;
1111
+ if (this.callbacks.onLivenessUpdate) {
1112
+ this.callbacks.onLivenessUpdate(state.stage, "Capturing...");
1113
+ }
1114
+ if (this.callbacks.onCaptureTrigger) {
1115
+ this.callbacks.onCaptureTrigger();
1116
+ }
1117
+ }
1118
+ } else {
1119
+ state.centerHold = 0;
1120
+ if (this.callbacks.onLivenessUpdate) {
1121
+ this.callbacks.onLivenessUpdate(state.stage, "Please look straight at the camera");
1122
+ }
1123
+ }
1087
1124
  }
1088
1125
  }
1089
1126
  }
@@ -1219,7 +1256,10 @@ function useFaceScan(videoRef, canvasRef, callbacks) {
1219
1256
  snapTriggered: false,
1220
1257
  lastResultsAt: 0,
1221
1258
  stage: "CENTER",
1222
- livenessReady: false
1259
+ livenessReady: false,
1260
+ currentYaw: null,
1261
+ currentAbsYaw: null,
1262
+ livenessCompleted: false
1223
1263
  });
1224
1264
  React.useEffect(() => {
1225
1265
  livenessStateRef.current.centerHold = refs.centerHold.current;
@@ -1240,6 +1280,22 @@ function useFaceScan(videoRef, canvasRef, callbacks) {
1240
1280
  }, []);
1241
1281
  const handleFaceCapture = React.useCallback(async () => {
1242
1282
  if (!videoRef.current) return;
1283
+ const reducedThreshold = 0.08;
1284
+ const currentAbsYaw = livenessStateRef.current.currentAbsYaw;
1285
+ if (currentAbsYaw === null || currentAbsYaw === void 0) {
1286
+ setState((prev) => ({
1287
+ ...prev,
1288
+ livenessInstruction: "Please position your face in front of the camera"
1289
+ }));
1290
+ return;
1291
+ }
1292
+ if (currentAbsYaw >= reducedThreshold) {
1293
+ setState((prev) => ({
1294
+ ...prev,
1295
+ livenessInstruction: "Please look straight at the camera before capturing"
1296
+ }));
1297
+ return;
1298
+ }
1243
1299
  setState((prev) => ({ ...prev, loading: true }));
1244
1300
  try {
1245
1301
  const video = videoRef.current;
@@ -1462,7 +1518,7 @@ function FaceScanModal({ onComplete }) {
1462
1518
  const errorData = error?.errorData || {};
1463
1519
  if (errorMessage.includes("Face already registered") || errorMessage.includes("already registered") || errorData?.message?.includes("Face already registered") || error?.statusCode === 500 && errorMessage.includes("Face")) {
1464
1520
  setToast({
1465
- message: "Face has already been registered for this session. Proceeding to document upload.",
1521
+ message: "Face already registered",
1466
1522
  type: "warning"
1467
1523
  });
1468
1524
  return;
@@ -1480,7 +1536,21 @@ function FaceScanModal({ onComplete }) {
1480
1536
  const checkSession = async () => {
1481
1537
  if (!apiService) return;
1482
1538
  try {
1483
- await apiService.checkSessionActive();
1539
+ const statusResponse = await apiService.getSessionStatus();
1540
+ const { completed_steps, next_step, status } = statusResponse.data;
1541
+ if (status !== "ACTIVE") {
1542
+ throw new Error("Session expired or inactive");
1543
+ }
1544
+ if (completed_steps.includes(COMPLETED_STEPS.FACE)) {
1545
+ setState((prev) => ({ ...prev, showDocumentUpload: true }));
1546
+ return;
1547
+ }
1548
+ if (next_step !== COMPLETED_STEPS.FACE && next_step !== COMPLETED_STEPS.INITIATED) {
1549
+ if (next_step === COMPLETED_STEPS.DOCS) {
1550
+ setState((prev) => ({ ...prev, showDocumentUpload: true }));
1551
+ return;
1552
+ }
1553
+ }
1484
1554
  setSessionError(null);
1485
1555
  } catch (error) {
1486
1556
  const message = error.message || "Session expired or inactive";
@@ -1491,7 +1561,7 @@ function FaceScanModal({ onComplete }) {
1491
1561
  }
1492
1562
  };
1493
1563
  checkSession();
1494
- }, [apiService, navigate]);
1564
+ }, [apiService, navigate, setState]);
1495
1565
  React.useEffect(() => {
1496
1566
  setState((prev) => ({ ...prev, cameraReady }));
1497
1567
  }, [cameraReady, setState]);