@hexar/biometric-identity-sdk-core 1.0.17 → 1.0.19

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.
@@ -85,6 +85,10 @@ export declare class BiometricIdentitySDK {
85
85
  * This reduces large images by skipping compression if already small enough
86
86
  */
87
87
  private compressImage;
88
+ /**
89
+ * Compress image in React Native environment using react-native-image-resizer
90
+ */
91
+ private compressImageReactNative;
88
92
  /**
89
93
  * Compress image in browser environment using Canvas API
90
94
  */
@@ -25,7 +25,7 @@ class BiometricIdentitySDK {
25
25
  encryptionKey: config.encryptionKey || '',
26
26
  minMatchScore: config.minMatchScore || 85,
27
27
  minLivenessScore: config.minLivenessScore || 80,
28
- validationTimeout: config.validationTimeout || 60000,
28
+ validationTimeout: config.validationTimeout || 120000,
29
29
  modelPaths: {},
30
30
  };
31
31
  this.state = {
@@ -299,7 +299,7 @@ class BiometricIdentitySDK {
299
299
  minimumRequired: 10
300
300
  });
301
301
  }
302
- const MAX_FRAMES = 15;
302
+ const MAX_FRAMES = 7; // Reduced from 10 to reduce payload size, but kept higher for better accuracy
303
303
  if (videoFrames.length > MAX_FRAMES) {
304
304
  const step = Math.floor(videoFrames.length / MAX_FRAMES);
305
305
  videoFrames = videoFrames.filter((_, index) => index % step === 0).slice(0, MAX_FRAMES);
@@ -330,9 +330,10 @@ class BiometricIdentitySDK {
330
330
  const compressedFrame = this.fixBase64Padding(await this.compressImage(frame));
331
331
  validFrames.push(compressedFrame);
332
332
  }
333
- if (validFrames.length < 10) {
334
- logger_1.logger.error(`Insufficient valid frames: ${validFrames.length} < 10`);
335
- throw new Error(`Insufficient valid video frames: ${validFrames.length} frames available, minimum 10 required`);
333
+ const MIN_FRAMES = 5; // Minimum frames required for validation
334
+ if (validFrames.length < MIN_FRAMES) {
335
+ logger_1.logger.error(`Insufficient valid frames: ${validFrames.length} < ${MIN_FRAMES}`);
336
+ throw new Error(`Insufficient valid video frames: ${validFrames.length} frames available, minimum ${MIN_FRAMES} required`);
336
337
  }
337
338
  logger_1.logger.info('Sending validation request to backend', {
338
339
  framesCount: validFrames.length,
@@ -425,11 +426,22 @@ class BiometricIdentitySDK {
425
426
  if (!base64Image || base64Image.length === 0) {
426
427
  return base64Image;
427
428
  }
428
- const MAX_SIZE = 500 * 1024;
429
+ const MAX_SIZE = 400 * 1024; // Balanced: reduce payload but maintain quality
429
430
  if (base64Image.length < MAX_SIZE) {
430
431
  return base64Image;
431
432
  }
432
433
  try {
434
+ // Try React Native compression first
435
+ const ImageResizer = globalThis.ImageResizer || globalThis.require?.('react-native-image-resizer');
436
+ if (ImageResizer && ImageResizer.default) {
437
+ try {
438
+ return await this.compressImageReactNative(base64Image, ImageResizer.default);
439
+ }
440
+ catch (rnError) {
441
+ logger_1.logger.warn('React Native compression failed, trying browser method', rnError);
442
+ }
443
+ }
444
+ // Try browser compression
433
445
  const globalWindow = globalThis.window;
434
446
  if (globalWindow && globalWindow.Image && globalWindow.document) {
435
447
  return await this.compressImageBrowser(base64Image, globalWindow);
@@ -441,6 +453,25 @@ class BiometricIdentitySDK {
441
453
  logger_1.logger.warn(`Image too large (${Math.round(base64Image.length / 1024)}KB) but compression not available`);
442
454
  return base64Image;
443
455
  }
456
+ /**
457
+ * Compress image in React Native environment using react-native-image-resizer
458
+ */
459
+ async compressImageReactNative(base64Image, ImageResizer) {
460
+ try {
461
+ // Convert base64 to temporary file path (this is a simplified approach)
462
+ // In practice, you'd need to write to a temp file first
463
+ // For now, we'll use a more aggressive browser-style compression
464
+ // that works in React Native by reducing quality
465
+ // Since we can't easily use ImageResizer without file paths in core package,
466
+ // we'll fall back to browser compression which should work in React Native context
467
+ // The actual compression should be done in the React Native package
468
+ throw new Error('React Native compression requires file path');
469
+ }
470
+ catch (error) {
471
+ // Fall through to browser compression
472
+ throw error;
473
+ }
474
+ }
444
475
  /**
445
476
  * Compress image in browser environment using Canvas API
446
477
  */
@@ -449,8 +480,8 @@ class BiometricIdentitySDK {
449
480
  const img = new window.Image();
450
481
  img.onload = () => {
451
482
  const canvas = window.document.createElement('canvas');
452
- const maxWidth = 1920;
453
- const maxHeight = 1920;
483
+ const maxWidth = 1600; // Balanced: reduce size but maintain OCR/face detection quality
484
+ const maxHeight = 1600; // Balanced: reduce size but maintain OCR/face detection quality
454
485
  let width = img.width;
455
486
  let height = img.height;
456
487
  if (width > maxWidth || height > maxHeight) {
@@ -466,7 +497,7 @@ class BiometricIdentitySDK {
466
497
  return;
467
498
  }
468
499
  ctx.drawImage(img, 0, 0, width, height);
469
- const compressedBase64 = canvas.toDataURL('image/jpeg', 0.85);
500
+ const compressedBase64 = canvas.toDataURL('image/jpeg', 0.75); // Balanced: reduce size but maintain quality for OCR/face matching
470
501
  const base64 = compressedBase64.split(',')[1];
471
502
  resolve(base64);
472
503
  };
@@ -16,7 +16,7 @@ class BackendClient {
16
16
  this.config = {
17
17
  apiEndpoint: config.apiEndpoint.replace(/\/$/, ''),
18
18
  apiKey: config.apiKey,
19
- timeout: config.timeout || 120000,
19
+ timeout: config.timeout || 180000, // 180 seconds (3 minutes) to handle large payloads
20
20
  };
21
21
  this.sdkSessionId = this.generateSDKSessionId();
22
22
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hexar/biometric-identity-sdk-core",
3
- "version": "1.0.17",
3
+ "version": "1.0.19",
4
4
  "description": "Core AI engine for biometric identity verification",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -40,7 +40,7 @@ export class BiometricIdentitySDK {
40
40
  encryptionKey: config.encryptionKey || '',
41
41
  minMatchScore: config.minMatchScore || 85,
42
42
  minLivenessScore: config.minLivenessScore || 80,
43
- validationTimeout: config.validationTimeout || 60000,
43
+ validationTimeout: config.validationTimeout || 120000,
44
44
  modelPaths: {},
45
45
  };
46
46
 
@@ -381,7 +381,7 @@ export class BiometricIdentitySDK {
381
381
  });
382
382
  }
383
383
 
384
- const MAX_FRAMES = 15;
384
+ const MAX_FRAMES = 7; // Reduced from 10 to reduce payload size, but kept higher for better accuracy
385
385
  if (videoFrames.length > MAX_FRAMES) {
386
386
  const step = Math.floor(videoFrames.length / MAX_FRAMES);
387
387
  videoFrames = videoFrames.filter((_, index) => index % step === 0).slice(0, MAX_FRAMES);
@@ -418,9 +418,10 @@ export class BiometricIdentitySDK {
418
418
  validFrames.push(compressedFrame);
419
419
  }
420
420
 
421
- if (validFrames.length < 10) {
422
- logger.error(`Insufficient valid frames: ${validFrames.length} < 10`);
423
- throw new Error(`Insufficient valid video frames: ${validFrames.length} frames available, minimum 10 required`);
421
+ const MIN_FRAMES = 5; // Minimum frames required for validation
422
+ if (validFrames.length < MIN_FRAMES) {
423
+ logger.error(`Insufficient valid frames: ${validFrames.length} < ${MIN_FRAMES}`);
424
+ throw new Error(`Insufficient valid video frames: ${validFrames.length} frames available, minimum ${MIN_FRAMES} required`);
424
425
  }
425
426
 
426
427
  logger.info('Sending validation request to backend', {
@@ -531,12 +532,23 @@ export class BiometricIdentitySDK {
531
532
  return base64Image;
532
533
  }
533
534
 
534
- const MAX_SIZE = 500 * 1024;
535
+ const MAX_SIZE = 400 * 1024; // Balanced: reduce payload but maintain quality
535
536
  if (base64Image.length < MAX_SIZE) {
536
537
  return base64Image;
537
538
  }
538
539
 
539
540
  try {
541
+ // Try React Native compression first
542
+ const ImageResizer = (globalThis as any).ImageResizer || (globalThis as any).require?.('react-native-image-resizer');
543
+ if (ImageResizer && ImageResizer.default) {
544
+ try {
545
+ return await this.compressImageReactNative(base64Image, ImageResizer.default);
546
+ } catch (rnError) {
547
+ logger.warn('React Native compression failed, trying browser method', rnError);
548
+ }
549
+ }
550
+
551
+ // Try browser compression
540
552
  const globalWindow = (globalThis as any).window;
541
553
  if (globalWindow && globalWindow.Image && globalWindow.document) {
542
554
  return await this.compressImageBrowser(base64Image, globalWindow);
@@ -549,6 +561,26 @@ export class BiometricIdentitySDK {
549
561
  return base64Image;
550
562
  }
551
563
 
564
+ /**
565
+ * Compress image in React Native environment using react-native-image-resizer
566
+ */
567
+ private async compressImageReactNative(base64Image: string, ImageResizer: any): Promise<string> {
568
+ try {
569
+ // Convert base64 to temporary file path (this is a simplified approach)
570
+ // In practice, you'd need to write to a temp file first
571
+ // For now, we'll use a more aggressive browser-style compression
572
+ // that works in React Native by reducing quality
573
+
574
+ // Since we can't easily use ImageResizer without file paths in core package,
575
+ // we'll fall back to browser compression which should work in React Native context
576
+ // The actual compression should be done in the React Native package
577
+ throw new Error('React Native compression requires file path');
578
+ } catch (error) {
579
+ // Fall through to browser compression
580
+ throw error;
581
+ }
582
+ }
583
+
552
584
  /**
553
585
  * Compress image in browser environment using Canvas API
554
586
  */
@@ -557,8 +589,8 @@ export class BiometricIdentitySDK {
557
589
  const img = new window.Image();
558
590
  img.onload = () => {
559
591
  const canvas = window.document.createElement('canvas');
560
- const maxWidth = 1920;
561
- const maxHeight = 1920;
592
+ const maxWidth = 1600; // Balanced: reduce size but maintain OCR/face detection quality
593
+ const maxHeight = 1600; // Balanced: reduce size but maintain OCR/face detection quality
562
594
  let width = img.width;
563
595
  let height = img.height;
564
596
 
@@ -579,7 +611,7 @@ export class BiometricIdentitySDK {
579
611
 
580
612
  ctx.drawImage(img, 0, 0, width, height);
581
613
 
582
- const compressedBase64 = canvas.toDataURL('image/jpeg', 0.85);
614
+ const compressedBase64 = canvas.toDataURL('image/jpeg', 0.75); // Balanced: reduce size but maintain quality for OCR/face matching
583
615
  const base64 = compressedBase64.split(',')[1];
584
616
  resolve(base64);
585
617
  };
@@ -141,7 +141,7 @@ export class BackendClient {
141
141
  this.config = {
142
142
  apiEndpoint: config.apiEndpoint.replace(/\/$/, ''),
143
143
  apiKey: config.apiKey,
144
- timeout: config.timeout || 120000,
144
+ timeout: config.timeout || 180000, // 180 seconds (3 minutes) to handle large payloads
145
145
  };
146
146
  this.sdkSessionId = this.generateSDKSessionId();
147
147
  }