@hexar/biometric-identity-sdk-core 1.0.10 → 1.0.12
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/BiometricIdentitySDK.js +44 -5
- package/dist/i18n/languages/en.js +1 -1
- package/dist/i18n/languages/es-AR.js +2 -2
- package/dist/i18n/languages/pt-BR.js +1 -1
- package/package.json +1 -1
- package/src/BiometricIdentitySDK.ts +51 -5
- package/src/i18n/languages/en.ts +1 -1
- package/src/i18n/languages/es-AR.ts +2 -2
- package/src/i18n/languages/pt-BR.ts +1 -1
|
@@ -183,12 +183,25 @@ class BiometricIdentitySDK {
|
|
|
183
183
|
*/
|
|
184
184
|
async storeVideoRecording(videoResult) {
|
|
185
185
|
try {
|
|
186
|
+
logger_1.logger.info('Storing video recording', {
|
|
187
|
+
framesCount: videoResult.frames?.length || 0,
|
|
188
|
+
duration: videoResult.duration,
|
|
189
|
+
hasSessionId: !!videoResult.sessionId
|
|
190
|
+
});
|
|
191
|
+
if (!videoResult.frames || videoResult.frames.length === 0) {
|
|
192
|
+
throw new Error('Video recording has no frames');
|
|
193
|
+
}
|
|
186
194
|
this.updateState({ isLoading: true, currentStep: types_1.SDKStep.RECORD_LIVENESS });
|
|
187
195
|
this.updateState({
|
|
188
196
|
videoData: videoResult,
|
|
189
197
|
progress: 75,
|
|
190
198
|
isLoading: false,
|
|
191
199
|
});
|
|
200
|
+
const stateAfterStore = this.getState();
|
|
201
|
+
logger_1.logger.info('Video recording stored', {
|
|
202
|
+
storedFramesCount: stateAfterStore.videoData?.frames?.length || 0,
|
|
203
|
+
hasVideoData: !!stateAfterStore.videoData
|
|
204
|
+
});
|
|
192
205
|
}
|
|
193
206
|
catch (error) {
|
|
194
207
|
this.handleError(error);
|
|
@@ -258,22 +271,48 @@ class BiometricIdentitySDK {
|
|
|
258
271
|
*/
|
|
259
272
|
async validateWithBackend() {
|
|
260
273
|
if (!this.state.frontID || !this.state.videoData) {
|
|
274
|
+
logger_1.logger.error('Validation failed: missing required data', {
|
|
275
|
+
hasFrontID: !!this.state.frontID,
|
|
276
|
+
hasVideoData: !!this.state.videoData
|
|
277
|
+
});
|
|
261
278
|
throw new Error('Required data not available');
|
|
262
279
|
}
|
|
280
|
+
logger_1.logger.info('Starting backend validation', {
|
|
281
|
+
videoFramesCount: this.state.videoData.frames?.length || 0,
|
|
282
|
+
videoDuration: this.state.videoData.duration,
|
|
283
|
+
hasBackID: !!this.state.backID
|
|
284
|
+
});
|
|
263
285
|
this.updateState({ progress: 80 });
|
|
264
286
|
try {
|
|
265
|
-
// Limit and sample video frames to prevent payload size issues
|
|
266
|
-
// Take max 30 frames, sampling evenly across the video
|
|
267
287
|
let videoFrames = this.state.videoData.frames;
|
|
268
|
-
if (videoFrames.length === 0) {
|
|
288
|
+
if (!videoFrames || videoFrames.length === 0) {
|
|
289
|
+
logger_1.logger.error('No video frames in state', {
|
|
290
|
+
videoDataExists: !!this.state.videoData,
|
|
291
|
+
framesProperty: typeof this.state.videoData.frames,
|
|
292
|
+
framesLength: this.state.videoData.frames?.length
|
|
293
|
+
});
|
|
269
294
|
throw new Error('No video frames available for validation');
|
|
270
295
|
}
|
|
271
|
-
|
|
296
|
+
if (videoFrames.length < 10) {
|
|
297
|
+
logger_1.logger.warn('Insufficient frames for validation', {
|
|
298
|
+
frameCount: videoFrames.length,
|
|
299
|
+
minimumRequired: 10
|
|
300
|
+
});
|
|
301
|
+
}
|
|
272
302
|
const MAX_FRAMES = 30;
|
|
273
303
|
if (videoFrames.length > MAX_FRAMES) {
|
|
274
304
|
const step = Math.floor(videoFrames.length / MAX_FRAMES);
|
|
275
305
|
videoFrames = videoFrames.filter((_, index) => index % step === 0).slice(0, MAX_FRAMES);
|
|
306
|
+
logger_1.logger.info('Sampled frames for validation', {
|
|
307
|
+
originalCount: this.state.videoData.frames.length,
|
|
308
|
+
sampledCount: videoFrames.length
|
|
309
|
+
});
|
|
276
310
|
}
|
|
311
|
+
logger_1.logger.info('Sending validation request to backend', {
|
|
312
|
+
framesCount: videoFrames.length,
|
|
313
|
+
duration: this.state.videoData.duration,
|
|
314
|
+
challengesCount: this.state.videoData.challengesCompleted?.length || 0
|
|
315
|
+
});
|
|
277
316
|
const response = await this.backendClient.fullValidation({
|
|
278
317
|
frontIdImage: this.state.frontID.data,
|
|
279
318
|
backIdImage: this.state.backID?.data,
|
|
@@ -282,10 +321,10 @@ class BiometricIdentitySDK {
|
|
|
282
321
|
challengesCompleted: this.state.videoData.challengesCompleted || [],
|
|
283
322
|
});
|
|
284
323
|
this.updateState({ progress: 95 });
|
|
285
|
-
// Convert backend response to SDK format
|
|
286
324
|
return this.backendClient.convertToValidationResult(response);
|
|
287
325
|
}
|
|
288
326
|
catch (error) {
|
|
327
|
+
logger_1.logger.error('Backend validation failed', error);
|
|
289
328
|
throw this.createError(types_1.BiometricErrorCode.NETWORK_ERROR, 'Backend validation failed', error);
|
|
290
329
|
}
|
|
291
330
|
}
|
|
@@ -66,7 +66,7 @@ exports.en = {
|
|
|
66
66
|
blink: 'Blink naturally',
|
|
67
67
|
turnHeadLeft: 'Turn your head to the left',
|
|
68
68
|
turnHeadRight: 'Turn your head to the right',
|
|
69
|
-
stayStill: '
|
|
69
|
+
stayStill: 'Follow the instructions',
|
|
70
70
|
openMouth: 'Open your mouth slightly',
|
|
71
71
|
},
|
|
72
72
|
recording: 'Recording...',
|
|
@@ -54,7 +54,7 @@ exports.esAR = {
|
|
|
54
54
|
liveness: {
|
|
55
55
|
title: 'Verificación Facial',
|
|
56
56
|
preparing: 'Preparando verificación...',
|
|
57
|
-
getReady: '¡
|
|
57
|
+
getReady: '¡Preparate!',
|
|
58
58
|
countdownMessage: 'Vas a realizar acciones.\nSeguí las instrucciones en pantalla.',
|
|
59
59
|
recordingInstructions: 'Mantené tu rostro visible y seguí las instrucciones',
|
|
60
60
|
instructions: {
|
|
@@ -66,7 +66,7 @@ exports.esAR = {
|
|
|
66
66
|
blink: 'Parpadeá naturalmente',
|
|
67
67
|
turnHeadLeft: 'Girá tu cabeza a la izquierda',
|
|
68
68
|
turnHeadRight: 'Girá tu cabeza a la derecha',
|
|
69
|
-
stayStill: '
|
|
69
|
+
stayStill: 'Segui las instrucciones',
|
|
70
70
|
openMouth: 'Abrí la boca ligeramente',
|
|
71
71
|
},
|
|
72
72
|
recording: 'Grabando...',
|
|
@@ -66,7 +66,7 @@ exports.ptBR = {
|
|
|
66
66
|
blink: 'Pisque naturalmente',
|
|
67
67
|
turnHeadLeft: 'Vire sua cabeça para a esquerda',
|
|
68
68
|
turnHeadRight: 'Vire sua cabeça para a direita',
|
|
69
|
-
stayStill: '
|
|
69
|
+
stayStill: 'Siga as instruções',
|
|
70
70
|
openMouth: 'Abra a boca levemente',
|
|
71
71
|
},
|
|
72
72
|
recording: 'Gravando...',
|
package/package.json
CHANGED
|
@@ -236,6 +236,16 @@ export class BiometricIdentitySDK {
|
|
|
236
236
|
*/
|
|
237
237
|
async storeVideoRecording(videoResult: VideoResult): Promise<void> {
|
|
238
238
|
try {
|
|
239
|
+
logger.info('Storing video recording', {
|
|
240
|
+
framesCount: videoResult.frames?.length || 0,
|
|
241
|
+
duration: videoResult.duration,
|
|
242
|
+
hasSessionId: !!videoResult.sessionId
|
|
243
|
+
});
|
|
244
|
+
|
|
245
|
+
if (!videoResult.frames || videoResult.frames.length === 0) {
|
|
246
|
+
throw new Error('Video recording has no frames');
|
|
247
|
+
}
|
|
248
|
+
|
|
239
249
|
this.updateState({ isLoading: true, currentStep: SDKStep.RECORD_LIVENESS });
|
|
240
250
|
|
|
241
251
|
this.updateState({
|
|
@@ -244,6 +254,12 @@ export class BiometricIdentitySDK {
|
|
|
244
254
|
isLoading: false,
|
|
245
255
|
});
|
|
246
256
|
|
|
257
|
+
const stateAfterStore = this.getState();
|
|
258
|
+
logger.info('Video recording stored', {
|
|
259
|
+
storedFramesCount: stateAfterStore.videoData?.frames?.length || 0,
|
|
260
|
+
hasVideoData: !!stateAfterStore.videoData
|
|
261
|
+
});
|
|
262
|
+
|
|
247
263
|
} catch (error) {
|
|
248
264
|
this.handleError(error);
|
|
249
265
|
throw error;
|
|
@@ -331,26 +347,56 @@ export class BiometricIdentitySDK {
|
|
|
331
347
|
*/
|
|
332
348
|
private async validateWithBackend(): Promise<ValidationResult> {
|
|
333
349
|
if (!this.state.frontID || !this.state.videoData) {
|
|
350
|
+
logger.error('Validation failed: missing required data', {
|
|
351
|
+
hasFrontID: !!this.state.frontID,
|
|
352
|
+
hasVideoData: !!this.state.videoData
|
|
353
|
+
});
|
|
334
354
|
throw new Error('Required data not available');
|
|
335
355
|
}
|
|
336
356
|
|
|
357
|
+
logger.info('Starting backend validation', {
|
|
358
|
+
videoFramesCount: this.state.videoData.frames?.length || 0,
|
|
359
|
+
videoDuration: this.state.videoData.duration,
|
|
360
|
+
hasBackID: !!this.state.backID
|
|
361
|
+
});
|
|
362
|
+
|
|
337
363
|
this.updateState({ progress: 80 });
|
|
338
364
|
|
|
339
365
|
try {
|
|
340
|
-
// Limit and sample video frames to prevent payload size issues
|
|
341
|
-
// Take max 30 frames, sampling evenly across the video
|
|
342
366
|
let videoFrames = this.state.videoData.frames;
|
|
343
|
-
|
|
367
|
+
|
|
368
|
+
if (!videoFrames || videoFrames.length === 0) {
|
|
369
|
+
logger.error('No video frames in state', {
|
|
370
|
+
videoDataExists: !!this.state.videoData,
|
|
371
|
+
framesProperty: typeof this.state.videoData.frames,
|
|
372
|
+
framesLength: this.state.videoData.frames?.length
|
|
373
|
+
});
|
|
344
374
|
throw new Error('No video frames available for validation');
|
|
345
375
|
}
|
|
376
|
+
|
|
377
|
+
if (videoFrames.length < 10) {
|
|
378
|
+
logger.warn('Insufficient frames for validation', {
|
|
379
|
+
frameCount: videoFrames.length,
|
|
380
|
+
minimumRequired: 10
|
|
381
|
+
});
|
|
382
|
+
}
|
|
346
383
|
|
|
347
|
-
// Sample frames if we have too many (max 30 frames to keep payload reasonable)
|
|
348
384
|
const MAX_FRAMES = 30;
|
|
349
385
|
if (videoFrames.length > MAX_FRAMES) {
|
|
350
386
|
const step = Math.floor(videoFrames.length / MAX_FRAMES);
|
|
351
387
|
videoFrames = videoFrames.filter((_, index) => index % step === 0).slice(0, MAX_FRAMES);
|
|
388
|
+
logger.info('Sampled frames for validation', {
|
|
389
|
+
originalCount: this.state.videoData.frames.length,
|
|
390
|
+
sampledCount: videoFrames.length
|
|
391
|
+
});
|
|
352
392
|
}
|
|
353
393
|
|
|
394
|
+
logger.info('Sending validation request to backend', {
|
|
395
|
+
framesCount: videoFrames.length,
|
|
396
|
+
duration: this.state.videoData.duration,
|
|
397
|
+
challengesCount: this.state.videoData.challengesCompleted?.length || 0
|
|
398
|
+
});
|
|
399
|
+
|
|
354
400
|
const response = await this.backendClient.fullValidation({
|
|
355
401
|
frontIdImage: this.state.frontID.data,
|
|
356
402
|
backIdImage: this.state.backID?.data,
|
|
@@ -361,9 +407,9 @@ export class BiometricIdentitySDK {
|
|
|
361
407
|
|
|
362
408
|
this.updateState({ progress: 95 });
|
|
363
409
|
|
|
364
|
-
// Convert backend response to SDK format
|
|
365
410
|
return this.backendClient.convertToValidationResult(response);
|
|
366
411
|
} catch (error) {
|
|
412
|
+
logger.error('Backend validation failed', error);
|
|
367
413
|
throw this.createError(
|
|
368
414
|
BiometricErrorCode.NETWORK_ERROR,
|
|
369
415
|
'Backend validation failed',
|
package/src/i18n/languages/en.ts
CHANGED
|
@@ -69,7 +69,7 @@ export const en: LanguageStrings = {
|
|
|
69
69
|
blink: 'Blink naturally',
|
|
70
70
|
turnHeadLeft: 'Turn your head to the left',
|
|
71
71
|
turnHeadRight: 'Turn your head to the right',
|
|
72
|
-
stayStill: '
|
|
72
|
+
stayStill: 'Follow the instructions',
|
|
73
73
|
openMouth: 'Open your mouth slightly',
|
|
74
74
|
},
|
|
75
75
|
recording: 'Recording...',
|
|
@@ -57,7 +57,7 @@ export const esAR: LanguageStrings = {
|
|
|
57
57
|
liveness: {
|
|
58
58
|
title: 'Verificación Facial',
|
|
59
59
|
preparing: 'Preparando verificación...',
|
|
60
|
-
getReady: '¡
|
|
60
|
+
getReady: '¡Preparate!',
|
|
61
61
|
countdownMessage: 'Vas a realizar acciones.\nSeguí las instrucciones en pantalla.',
|
|
62
62
|
recordingInstructions: 'Mantené tu rostro visible y seguí las instrucciones',
|
|
63
63
|
instructions: {
|
|
@@ -69,7 +69,7 @@ export const esAR: LanguageStrings = {
|
|
|
69
69
|
blink: 'Parpadeá naturalmente',
|
|
70
70
|
turnHeadLeft: 'Girá tu cabeza a la izquierda',
|
|
71
71
|
turnHeadRight: 'Girá tu cabeza a la derecha',
|
|
72
|
-
stayStill: '
|
|
72
|
+
stayStill: 'Segui las instrucciones',
|
|
73
73
|
openMouth: 'Abrí la boca ligeramente',
|
|
74
74
|
},
|
|
75
75
|
recording: 'Grabando...',
|
|
@@ -69,7 +69,7 @@ export const ptBR: LanguageStrings = {
|
|
|
69
69
|
blink: 'Pisque naturalmente',
|
|
70
70
|
turnHeadLeft: 'Vire sua cabeça para a esquerda',
|
|
71
71
|
turnHeadRight: 'Vire sua cabeça para a direita',
|
|
72
|
-
stayStill: '
|
|
72
|
+
stayStill: 'Siga as instruções',
|
|
73
73
|
openMouth: 'Abra a boca levemente',
|
|
74
74
|
},
|
|
75
75
|
recording: 'Gravando...',
|