@neofaceid/web-sdk 1.4.0 → 1.4.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.
|
@@ -4,6 +4,7 @@ var __publicField = (obj, key, value) => {
|
|
|
4
4
|
__defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
5
5
|
return value;
|
|
6
6
|
};
|
|
7
|
+
var _a;
|
|
7
8
|
import require$$0$1, { useRef, useState, useCallback, useReducer, useEffect } from "react";
|
|
8
9
|
import require$$0 from "react-dom";
|
|
9
10
|
import * as faceapi from "face-api.js";
|
|
@@ -1006,7 +1007,7 @@ const useCamera = () => {
|
|
|
1006
1007
|
};
|
|
1007
1008
|
const startCamera = useCallback(
|
|
1008
1009
|
async (constraints) => {
|
|
1009
|
-
var
|
|
1010
|
+
var _a2;
|
|
1010
1011
|
console.log("🎬 [useCamera] startCamera chamado", {
|
|
1011
1012
|
hasExistingStream: !!streamRef.current,
|
|
1012
1013
|
isInitializing: isInitializingRef.current
|
|
@@ -1048,7 +1049,7 @@ const useCamera = () => {
|
|
|
1048
1049
|
console.log("📋 [useCamera] Detalhes do erro:", {
|
|
1049
1050
|
name: error.name,
|
|
1050
1051
|
message: error.message,
|
|
1051
|
-
stack: (
|
|
1052
|
+
stack: (_a2 = error.stack) == null ? void 0 : _a2.substring(0, 200)
|
|
1052
1053
|
});
|
|
1053
1054
|
if (error.name === "NotAllowedError" || error.name === "PermissionDeniedError") {
|
|
1054
1055
|
throw new CameraPermissionDenied(
|
|
@@ -1135,10 +1136,11 @@ class NeoFaceError extends Error {
|
|
|
1135
1136
|
this.type = type;
|
|
1136
1137
|
}
|
|
1137
1138
|
}
|
|
1138
|
-
const API_BASE_URL = "
|
|
1139
|
+
const API_BASE_URL = ((_a = { "BASE_URL": "/", "MODE": "production", "DEV": false, "PROD": true, "SSR": false }) == null ? void 0 : _a.VITE_API_BASE_URL) || "http://localhost:8000";
|
|
1139
1140
|
const REQUEST_TIMEOUT = 1e4;
|
|
1140
1141
|
const ensureSecureContext = () => {
|
|
1141
|
-
|
|
1142
|
+
const isLocalhost = window.location.hostname === "localhost" || window.location.hostname === "127.0.0.1" || window.location.hostname === "";
|
|
1143
|
+
if (!window.isSecureContext && !isLocalhost) {
|
|
1142
1144
|
throw new NeoFaceError(
|
|
1143
1145
|
"Secure context (HTTPS) is required for this operation",
|
|
1144
1146
|
ErrorType.NETWORK
|
|
@@ -1184,7 +1186,7 @@ const validateToken = async (applicationToken) => {
|
|
|
1184
1186
|
ensureSecureContext();
|
|
1185
1187
|
const controller = createTimeoutController();
|
|
1186
1188
|
try {
|
|
1187
|
-
const response = await fetch(`${API_BASE_URL}/api/v1/
|
|
1189
|
+
const response = await fetch(`${API_BASE_URL}/api/v1/auth/application/validate_token/`, {
|
|
1188
1190
|
method: "POST",
|
|
1189
1191
|
headers: {
|
|
1190
1192
|
"Content-Type": "application/json",
|
|
@@ -1444,7 +1446,7 @@ const recognize = async (image, applicationToken) => {
|
|
|
1444
1446
|
}
|
|
1445
1447
|
};
|
|
1446
1448
|
const loginWithBiometric$1 = async (image, applicationToken) => {
|
|
1447
|
-
var
|
|
1449
|
+
var _a2, _b, _c, _d, _e;
|
|
1448
1450
|
ensureSecureContext();
|
|
1449
1451
|
const controller = createTimeoutController();
|
|
1450
1452
|
const compressedImage = await compressImage(image);
|
|
@@ -1474,7 +1476,7 @@ const loginWithBiometric$1 = async (image, applicationToken) => {
|
|
|
1474
1476
|
accessToken: data.accessToken,
|
|
1475
1477
|
alias: data.alias,
|
|
1476
1478
|
user: {
|
|
1477
|
-
id: ((
|
|
1479
|
+
id: ((_a2 = data.user) == null ? void 0 : _a2.id) || "",
|
|
1478
1480
|
email: ((_b = data.user) == null ? void 0 : _b.email) || "",
|
|
1479
1481
|
role: ((_c = data.user) == null ? void 0 : _c.role) || "",
|
|
1480
1482
|
validated: ((_d = data.user) == null ? void 0 : _d.validated) || false,
|
|
@@ -1687,6 +1689,7 @@ const registerPersonWithoutFace = async (personData, applicationToken) => {
|
|
|
1687
1689
|
}
|
|
1688
1690
|
};
|
|
1689
1691
|
const registerPersonWithBiometric = async (personData, facePhotos, applicationToken) => {
|
|
1692
|
+
var _a2, _b, _c, _d, _e, _f, _g, _h;
|
|
1690
1693
|
ensureSecureContext();
|
|
1691
1694
|
if (!facePhotos || facePhotos.length === 0) {
|
|
1692
1695
|
throw new NeoFaceError("At least one face photo is required for biometric registration", ErrorType.VALIDATION_ERROR);
|
|
@@ -1733,29 +1736,56 @@ const registerPersonWithBiometric = async (personData, facePhotos, applicationTo
|
|
|
1733
1736
|
}
|
|
1734
1737
|
try {
|
|
1735
1738
|
const errorData = await response.json();
|
|
1739
|
+
if (errorData.errors) {
|
|
1740
|
+
const errorMessages = Object.entries(errorData.errors).map(([field, messages]) => {
|
|
1741
|
+
const fieldName = field === "password" ? "senha" : field === "password_confirm" ? "confirmação de senha" : field;
|
|
1742
|
+
const messageList = Array.isArray(messages) ? messages.join(", ") : String(messages);
|
|
1743
|
+
return `${fieldName}: ${messageList}`;
|
|
1744
|
+
}).join("; ");
|
|
1745
|
+
throw new NeoFaceError(`Erro de validação: ${errorMessages}`, ErrorType.VALIDATION_ERROR);
|
|
1746
|
+
}
|
|
1736
1747
|
if (errorData.error === "fraud_detected") {
|
|
1737
1748
|
throw new NeoFaceError("Fraud detected in biometric images. Registration blocked.", ErrorType.VALIDATION_ERROR);
|
|
1738
1749
|
}
|
|
1739
|
-
if (errorData.error === "user_exists") {
|
|
1750
|
+
if (errorData.error === "user_exists" || errorData.error_code === "ALREADY_EXISTS") {
|
|
1740
1751
|
throw new NeoFaceError("User with this email already exists", ErrorType.VALIDATION_ERROR);
|
|
1741
1752
|
}
|
|
1742
1753
|
if (errorData.error === "person_exists") {
|
|
1743
1754
|
throw new NeoFaceError("Person with this CPF already exists", ErrorType.VALIDATION_ERROR);
|
|
1744
1755
|
}
|
|
1745
|
-
|
|
1756
|
+
const errorMessage = errorData.message || errorData.error || `Server returned status ${response.status}`;
|
|
1757
|
+
throw new NeoFaceError(errorMessage, ErrorType.VALIDATION_ERROR);
|
|
1746
1758
|
} catch (parseError) {
|
|
1759
|
+
if (parseError instanceof NeoFaceError) {
|
|
1760
|
+
throw parseError;
|
|
1761
|
+
}
|
|
1747
1762
|
throw new NeoFaceError(`Server returned status ${response.status}`, ErrorType.NETWORK);
|
|
1748
1763
|
}
|
|
1749
1764
|
}
|
|
1750
1765
|
const data = await response.json();
|
|
1766
|
+
if (response.status === 202 && ((_a2 = data.data) == null ? void 0 : _a2.task_id)) {
|
|
1767
|
+
return {
|
|
1768
|
+
success: data.success,
|
|
1769
|
+
message: data.message || "Registration is being processed. You will receive an email when completed.",
|
|
1770
|
+
task_id: data.data.task_id,
|
|
1771
|
+
status: data.data.status || "processing",
|
|
1772
|
+
person_id: void 0,
|
|
1773
|
+
user_id: void 0,
|
|
1774
|
+
person_validated: void 0,
|
|
1775
|
+
face_processing: void 0,
|
|
1776
|
+
onboarding_link: void 0
|
|
1777
|
+
};
|
|
1778
|
+
}
|
|
1751
1779
|
return {
|
|
1752
1780
|
success: data.success,
|
|
1753
1781
|
message: data.message,
|
|
1754
|
-
person_id: data.person_id,
|
|
1755
|
-
user_id: data.user_id,
|
|
1756
|
-
person_validated: data.person_validated,
|
|
1757
|
-
face_processing: data.face_processing,
|
|
1758
|
-
onboarding_link: data.onboarding_link
|
|
1782
|
+
person_id: ((_b = data.data) == null ? void 0 : _b.person_id) || data.person_id,
|
|
1783
|
+
user_id: ((_c = data.data) == null ? void 0 : _c.user_id) || data.user_id,
|
|
1784
|
+
person_validated: ((_d = data.data) == null ? void 0 : _d.person_validated) || data.person_validated,
|
|
1785
|
+
face_processing: ((_e = data.data) == null ? void 0 : _e.face_processing) || data.face_processing,
|
|
1786
|
+
onboarding_link: ((_f = data.data) == null ? void 0 : _f.onboarding_link) || data.onboarding_link,
|
|
1787
|
+
task_id: (_g = data.data) == null ? void 0 : _g.task_id,
|
|
1788
|
+
status: (_h = data.data) == null ? void 0 : _h.status
|
|
1759
1789
|
};
|
|
1760
1790
|
} catch (error) {
|
|
1761
1791
|
if (error instanceof Error) {
|
|
@@ -1817,7 +1847,7 @@ const loginWithEmail = async (email, password, applicationToken) => {
|
|
|
1817
1847
|
}
|
|
1818
1848
|
};
|
|
1819
1849
|
const identifyPerson = async (image, applicationToken) => {
|
|
1820
|
-
var
|
|
1850
|
+
var _a2, _b;
|
|
1821
1851
|
ensureSecureContext();
|
|
1822
1852
|
const controller = createTimeoutController();
|
|
1823
1853
|
const compressedImage = await compressImage(image);
|
|
@@ -1853,7 +1883,7 @@ const identifyPerson = async (image, applicationToken) => {
|
|
|
1853
1883
|
if (!data.success) {
|
|
1854
1884
|
throw new NeoFaceError(data.message || "Person identification failed", ErrorType.RECOGNITION_FAILED);
|
|
1855
1885
|
}
|
|
1856
|
-
const personName = ((
|
|
1886
|
+
const personName = ((_a2 = data.person) == null ? void 0 : _a2.name) || "";
|
|
1857
1887
|
const birthDateStr = (_b = data.person) == null ? void 0 : _b.birth_date;
|
|
1858
1888
|
if (!personName) {
|
|
1859
1889
|
throw new NeoFaceError("Person name not found in response", ErrorType.PERSON_NOT_FOUND);
|
|
@@ -2129,8 +2159,8 @@ function FaceCaptureModal({ accessToken, onClose, onSuccess }) {
|
|
|
2129
2159
|
canvasRef.current.height = videoRef.current.videoHeight;
|
|
2130
2160
|
context.drawImage(videoRef.current, 0, 0, canvasRef.current.width, canvasRef.current.height);
|
|
2131
2161
|
const blob = await new Promise((resolve, reject) => {
|
|
2132
|
-
var
|
|
2133
|
-
(
|
|
2162
|
+
var _a2;
|
|
2163
|
+
(_a2 = canvasRef.current) == null ? void 0 : _a2.toBlob(
|
|
2134
2164
|
(b) => {
|
|
2135
2165
|
if (b)
|
|
2136
2166
|
resolve(b);
|
|
@@ -2267,8 +2297,8 @@ function BiometricRegistrationModal({
|
|
|
2267
2297
|
onClose,
|
|
2268
2298
|
onSuccess,
|
|
2269
2299
|
onError,
|
|
2270
|
-
useRealApi =
|
|
2271
|
-
//
|
|
2300
|
+
useRealApi = true
|
|
2301
|
+
// Sempre usa API real em produção
|
|
2272
2302
|
}) {
|
|
2273
2303
|
const videoRef = useRef(null);
|
|
2274
2304
|
const canvasRef = useRef(null);
|
|
@@ -2530,8 +2560,8 @@ function BiometricRegistrationModal({
|
|
|
2530
2560
|
}
|
|
2531
2561
|
};
|
|
2532
2562
|
const startTimer = setTimeout(() => {
|
|
2533
|
-
var
|
|
2534
|
-
if (isRunning && ((
|
|
2563
|
+
var _a2;
|
|
2564
|
+
if (isRunning && ((_a2 = videoRef.current) == null ? void 0 : _a2.readyState) === 4) {
|
|
2535
2565
|
detectFace2();
|
|
2536
2566
|
}
|
|
2537
2567
|
}, 1e3);
|
|
@@ -2592,60 +2622,19 @@ function BiometricRegistrationModal({
|
|
|
2592
2622
|
};
|
|
2593
2623
|
const processRegistration = async (photos) => {
|
|
2594
2624
|
try {
|
|
2595
|
-
|
|
2596
|
-
|
|
2597
|
-
|
|
2598
|
-
|
|
2599
|
-
|
|
2600
|
-
|
|
2601
|
-
|
|
2602
|
-
|
|
2603
|
-
|
|
2604
|
-
|
|
2605
|
-
onboarding_link: result2.onboarding_link
|
|
2606
|
-
};
|
|
2607
|
-
dispatch({ type: "SUCCESS" });
|
|
2608
|
-
onSuccess(adaptedResult);
|
|
2609
|
-
return;
|
|
2610
|
-
}
|
|
2611
|
-
console.log("🎭 Usando modo SIMULADO para testes...");
|
|
2612
|
-
const facePhotosBase64 = await Promise.all(
|
|
2613
|
-
photos.map(async (photo) => {
|
|
2614
|
-
return new Promise((resolve, reject) => {
|
|
2615
|
-
const reader = new FileReader();
|
|
2616
|
-
reader.onload = () => {
|
|
2617
|
-
const result2 = reader.result;
|
|
2618
|
-
resolve(result2);
|
|
2619
|
-
};
|
|
2620
|
-
reader.onerror = reject;
|
|
2621
|
-
reader.readAsDataURL(photo);
|
|
2622
|
-
});
|
|
2623
|
-
})
|
|
2624
|
-
);
|
|
2625
|
-
await new Promise((resolve) => setTimeout(resolve, 2e3));
|
|
2626
|
-
const result = {
|
|
2627
|
-
success: true,
|
|
2628
|
-
message: "Registro biométrico realizado com sucesso",
|
|
2629
|
-
person_id: "test-person-123",
|
|
2630
|
-
user_id: "test-user-456",
|
|
2631
|
-
person_validated: true,
|
|
2632
|
-
face_processing: {
|
|
2633
|
-
total_photos_captured: photos.length,
|
|
2634
|
-
photo_sizes: photos.map((p, i) => ({
|
|
2635
|
-
photo_index: i + 1,
|
|
2636
|
-
size_kb: Math.round(p.size / 1024)
|
|
2637
|
-
})),
|
|
2638
|
-
// Mostra apenas preview dos primeiros 50 caracteres de cada foto em base64
|
|
2639
|
-
photos_preview: facePhotosBase64.map((b64, i) => ({
|
|
2640
|
-
photo_index: i + 1,
|
|
2641
|
-
format: "data:image/jpeg;base64,...",
|
|
2642
|
-
preview: b64.substring(0, 50) + "...",
|
|
2643
|
-
full_length: b64.length
|
|
2644
|
-
}))
|
|
2645
|
-
}
|
|
2625
|
+
console.log("🚀 Fazendo requisição ao backend...");
|
|
2626
|
+
const result = await registerPersonWithBiometric(personData, photos, applicationToken);
|
|
2627
|
+
const adaptedResult = {
|
|
2628
|
+
success: result.success,
|
|
2629
|
+
message: result.message,
|
|
2630
|
+
person_id: result.person_id,
|
|
2631
|
+
user_id: result.user_id,
|
|
2632
|
+
person_validated: result.person_validated,
|
|
2633
|
+
face_processing: result.face_processing,
|
|
2634
|
+
onboarding_link: result.onboarding_link
|
|
2646
2635
|
};
|
|
2647
2636
|
dispatch({ type: "SUCCESS" });
|
|
2648
|
-
onSuccess(
|
|
2637
|
+
onSuccess(adaptedResult);
|
|
2649
2638
|
} catch (error) {
|
|
2650
2639
|
const errorMessage = error instanceof Error ? error.message : "Erro desconhecido";
|
|
2651
2640
|
dispatch({ type: "ERROR", message: errorMessage });
|
|
@@ -3529,21 +3518,21 @@ let BiometricCaptureModal$1 = class BiometricCaptureModal2 {
|
|
|
3529
3518
|
const cancelBtn = this.modal.querySelector(".neofaceid-cancel-btn");
|
|
3530
3519
|
const captureBtn = this.modal.querySelector(".neofaceid-capture-btn");
|
|
3531
3520
|
closeBtn == null ? void 0 : closeBtn.addEventListener("click", () => {
|
|
3532
|
-
var
|
|
3521
|
+
var _a2, _b;
|
|
3533
3522
|
this.close();
|
|
3534
|
-
(_b = (
|
|
3523
|
+
(_b = (_a2 = this.options).onCancel) == null ? void 0 : _b.call(_a2);
|
|
3535
3524
|
});
|
|
3536
3525
|
cancelBtn == null ? void 0 : cancelBtn.addEventListener("click", () => {
|
|
3537
|
-
var
|
|
3526
|
+
var _a2, _b;
|
|
3538
3527
|
this.close();
|
|
3539
|
-
(_b = (
|
|
3528
|
+
(_b = (_a2 = this.options).onCancel) == null ? void 0 : _b.call(_a2);
|
|
3540
3529
|
});
|
|
3541
3530
|
captureBtn == null ? void 0 : captureBtn.addEventListener("click", () => {
|
|
3542
3531
|
this.captureImage();
|
|
3543
3532
|
});
|
|
3544
3533
|
this.modal.addEventListener("click", (e) => {
|
|
3545
|
-
var
|
|
3546
|
-
if (e.target === ((
|
|
3534
|
+
var _a2, _b, _c;
|
|
3535
|
+
if (e.target === ((_a2 = this.modal) == null ? void 0 : _a2.querySelector(".neofaceid-modal-overlay"))) {
|
|
3547
3536
|
this.close();
|
|
3548
3537
|
(_c = (_b = this.options).onCancel) == null ? void 0 : _c.call(_b);
|
|
3549
3538
|
}
|
|
@@ -4000,7 +3989,7 @@ function BiometricStatusOverlayComponent({ status, onClose }) {
|
|
|
4000
3989
|
alt: "NeoFaceId",
|
|
4001
3990
|
className: `neofaceid-logo ${status === "verifying" ? "pulsing" : ""}`,
|
|
4002
3991
|
onError: (e) => {
|
|
4003
|
-
var
|
|
3992
|
+
var _a2;
|
|
4004
3993
|
const img = e.target;
|
|
4005
3994
|
img.style.display = "none";
|
|
4006
3995
|
const fallback = document.createElement("div");
|
|
@@ -4011,7 +4000,7 @@ function BiometricStatusOverlayComponent({ status, onClose }) {
|
|
|
4011
4000
|
</svg>
|
|
4012
4001
|
`;
|
|
4013
4002
|
fallback.style.cssText = "width: 80px; height: 80px; display: flex; align-items: center; justify-content: center;";
|
|
4014
|
-
(
|
|
4003
|
+
(_a2 = img.parentElement) == null ? void 0 : _a2.appendChild(fallback);
|
|
4015
4004
|
}
|
|
4016
4005
|
}
|
|
4017
4006
|
) }),
|
|
@@ -5229,7 +5218,7 @@ const biometricDetection = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.
|
|
|
5229
5218
|
initializeBiometricDetection,
|
|
5230
5219
|
isAdvancedDetectionAvailable
|
|
5231
5220
|
}, Symbol.toStringTag, { value: "Module" }));
|
|
5232
|
-
const VERSION = "1.4.
|
|
5221
|
+
const VERSION = "1.4.2";
|
|
5233
5222
|
const RELEASE_DATE = "2025-11-23";
|
|
5234
5223
|
class OnboardingCaptureModal {
|
|
5235
5224
|
constructor(options) {
|
|
@@ -5496,8 +5485,8 @@ function startBiometricRegistration(personData, applicationToken, callbacks, opt
|
|
|
5496
5485
|
const modalElement = require$$0$1.createElement(BiometricRegistrationModal, {
|
|
5497
5486
|
personData,
|
|
5498
5487
|
applicationToken,
|
|
5499
|
-
useRealApi: (options == null ? void 0 : options.useRealApi)
|
|
5500
|
-
//
|
|
5488
|
+
useRealApi: (options == null ? void 0 : options.useRealApi) ?? true,
|
|
5489
|
+
// Sempre usa API real em produção
|
|
5501
5490
|
onClose: cleanup,
|
|
5502
5491
|
onSuccess: (result) => {
|
|
5503
5492
|
cleanup();
|