@hexar/biometric-identity-sdk-core 1.0.12 → 1.0.14

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.
@@ -311,7 +311,9 @@ class BiometricIdentitySDK {
311
311
  logger_1.logger.info('Sending validation request to backend', {
312
312
  framesCount: videoFrames.length,
313
313
  duration: this.state.videoData.duration,
314
- challengesCount: this.state.videoData.challengesCompleted?.length || 0
314
+ challengesCount: this.state.videoData.challengesCompleted?.length || 0,
315
+ frontImageSize: this.state.frontID.data?.length || 0,
316
+ backImageSize: this.state.backID?.data?.length || 0
315
317
  });
316
318
  const response = await this.backendClient.fullValidation({
317
319
  frontIdImage: this.state.frontID.data,
@@ -324,8 +326,22 @@ class BiometricIdentitySDK {
324
326
  return this.backendClient.convertToValidationResult(response);
325
327
  }
326
328
  catch (error) {
327
- logger_1.logger.error('Backend validation failed', error);
328
- throw this.createError(types_1.BiometricErrorCode.NETWORK_ERROR, 'Backend validation failed', error);
329
+ logger_1.logger.error('Backend validation failed', {
330
+ errorMessage: error?.message,
331
+ errorName: error?.name,
332
+ status: error?.status,
333
+ statusText: error?.statusText,
334
+ errorData: error?.errorData,
335
+ errorStack: error?.stack?.substring(0, 500)
336
+ });
337
+ const errorMessage = error?.message ||
338
+ (error?.status ? `Backend request failed with status ${error.status}` : 'Backend validation failed');
339
+ throw this.createError(types_1.BiometricErrorCode.NETWORK_ERROR, errorMessage, {
340
+ status: error?.status,
341
+ statusText: error?.statusText,
342
+ errorData: error?.errorData,
343
+ originalError: error?.message
344
+ });
329
345
  }
330
346
  }
331
347
  /**
@@ -88,10 +88,10 @@ class BackendClient {
88
88
  */
89
89
  async fullValidation(params) {
90
90
  if (!this.currentSessionId) {
91
- // Generate a challenge first if no session exists
91
+ logger_1.logger.info('No session ID, generating challenge');
92
92
  await this.generateChallenge();
93
93
  }
94
- return this.request('/api/v1/validate', 'POST', {
94
+ const requestBody = {
95
95
  front_id_image: params.frontIdImage,
96
96
  back_id_image: params.backIdImage,
97
97
  video_frames: params.videoFrames,
@@ -101,7 +101,20 @@ class BackendClient {
101
101
  document_type: params.documentType,
102
102
  country_code: params.countryCode,
103
103
  device_info: params.deviceInfo,
104
+ };
105
+ logger_1.logger.info('Full validation request', {
106
+ hasSessionId: !!this.currentSessionId,
107
+ sessionId: this.currentSessionId,
108
+ videoFramesCount: params.videoFrames.length,
109
+ hasFrontImage: !!params.frontIdImage,
110
+ hasBackImage: !!params.backIdImage,
111
+ frontImageLength: params.frontIdImage?.length || 0,
112
+ backImageLength: params.backIdImage?.length || 0,
113
+ averageFrameLength: params.videoFrames.length > 0
114
+ ? Math.round(params.videoFrames.reduce((sum, f) => sum + f.length, 0) / params.videoFrames.length)
115
+ : 0
104
116
  });
117
+ return this.request('/api/v1/validate', 'POST', requestBody);
105
118
  }
106
119
  /**
107
120
  * Convert backend response to SDK ValidationResult format
@@ -171,6 +184,12 @@ class BackendClient {
171
184
  */
172
185
  async request(endpoint, method, body) {
173
186
  const url = `${this.config.apiEndpoint}${endpoint}`;
187
+ logger_1.logger.info('Making backend request', {
188
+ url,
189
+ method,
190
+ hasBody: !!body,
191
+ bodySize: body ? JSON.stringify(body).length : 0
192
+ });
174
193
  const controller = new AbortController();
175
194
  const timeoutId = setTimeout(() => controller.abort(), this.config.timeout);
176
195
  const headers = {
@@ -187,25 +206,65 @@ class BackendClient {
187
206
  body: body ? JSON.stringify(body) : undefined,
188
207
  signal: controller.signal,
189
208
  });
209
+ logger_1.logger.info('Backend response received', {
210
+ url,
211
+ status: response.status,
212
+ statusText: response.statusText,
213
+ ok: response.ok
214
+ });
190
215
  clearTimeout(timeoutId);
191
216
  if (!response.ok) {
192
- // Handle 413 Payload Too Large specifically
217
+ let errorText = '';
218
+ let errorData = {};
219
+ try {
220
+ errorText = await response.text();
221
+ if (errorText) {
222
+ try {
223
+ errorData = JSON.parse(errorText);
224
+ }
225
+ catch {
226
+ errorData = { raw: errorText };
227
+ }
228
+ }
229
+ }
230
+ catch (parseError) {
231
+ logger_1.logger.warn('Could not parse error response', parseError);
232
+ }
233
+ const errorMessage = errorData?.error?.message ||
234
+ errorData?.detail ||
235
+ errorData?.message ||
236
+ errorData?.raw ||
237
+ `Request failed with status ${response.status}: ${response.statusText}`;
238
+ logger_1.logger.error('Backend request failed', {
239
+ url,
240
+ method,
241
+ status: response.status,
242
+ statusText: response.statusText,
243
+ errorText: errorText.substring(0, 500),
244
+ errorData: JSON.stringify(errorData).substring(0, 500)
245
+ });
246
+ const error = new Error(errorMessage);
247
+ error.status = response.status;
248
+ error.statusText = response.statusText;
249
+ error.errorData = errorData;
193
250
  if (response.status === 413) {
194
251
  throw new Error(`Payload too large (413). The request body exceeds the server's size limit. Try reducing the number of video frames or image sizes.`);
195
252
  }
196
- const errorData = await response.json().catch(() => ({}));
197
- throw new Error(errorData?.error?.message ||
198
- errorData?.detail ||
199
- `Request failed with status ${response.status}`);
253
+ throw error;
200
254
  }
201
255
  return await response.json();
202
256
  }
203
257
  catch (error) {
204
258
  clearTimeout(timeoutId);
205
259
  if (error.name === 'AbortError') {
260
+ logger_1.logger.error('Request timeout', { url, method, timeout: this.config.timeout });
206
261
  throw new Error('Request timeout');
207
262
  }
208
- throw error;
263
+ if (error.message) {
264
+ throw error;
265
+ }
266
+ logger_1.logger.error('Unexpected request error', { url, method, error });
267
+ throw new Error('Network request failed');
209
268
  }
210
269
  }
211
270
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hexar/biometric-identity-sdk-core",
3
- "version": "1.0.12",
3
+ "version": "1.0.14",
4
4
  "description": "Core AI engine for biometric identity verification",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -394,7 +394,9 @@ export class BiometricIdentitySDK {
394
394
  logger.info('Sending validation request to backend', {
395
395
  framesCount: videoFrames.length,
396
396
  duration: this.state.videoData.duration,
397
- challengesCount: this.state.videoData.challengesCompleted?.length || 0
397
+ challengesCount: this.state.videoData.challengesCompleted?.length || 0,
398
+ frontImageSize: this.state.frontID.data?.length || 0,
399
+ backImageSize: this.state.backID?.data?.length || 0
398
400
  });
399
401
 
400
402
  const response = await this.backendClient.fullValidation({
@@ -408,12 +410,28 @@ export class BiometricIdentitySDK {
408
410
  this.updateState({ progress: 95 });
409
411
 
410
412
  return this.backendClient.convertToValidationResult(response);
411
- } catch (error) {
412
- logger.error('Backend validation failed', error);
413
+ } catch (error: any) {
414
+ logger.error('Backend validation failed', {
415
+ errorMessage: error?.message,
416
+ errorName: error?.name,
417
+ status: error?.status,
418
+ statusText: error?.statusText,
419
+ errorData: error?.errorData,
420
+ errorStack: error?.stack?.substring(0, 500)
421
+ });
422
+
423
+ const errorMessage = error?.message ||
424
+ (error?.status ? `Backend request failed with status ${error.status}` : 'Backend validation failed');
425
+
413
426
  throw this.createError(
414
427
  BiometricErrorCode.NETWORK_ERROR,
415
- 'Backend validation failed',
416
- error
428
+ errorMessage,
429
+ {
430
+ status: error?.status,
431
+ statusText: error?.statusText,
432
+ errorData: error?.errorData,
433
+ originalError: error?.message
434
+ }
417
435
  );
418
436
  }
419
437
  }
@@ -261,24 +261,39 @@ export class BackendClient {
261
261
  deviceInfo?: Record<string, any>;
262
262
  }): Promise<FullValidationResponse> {
263
263
  if (!this.currentSessionId) {
264
- // Generate a challenge first if no session exists
264
+ logger.info('No session ID, generating challenge');
265
265
  await this.generateChallenge();
266
266
  }
267
267
 
268
+ const requestBody = {
269
+ front_id_image: params.frontIdImage,
270
+ back_id_image: params.backIdImage,
271
+ video_frames: params.videoFrames,
272
+ video_duration_ms: params.videoDurationMs,
273
+ session_id: this.currentSessionId,
274
+ challenges_completed: params.challengesCompleted || [],
275
+ document_type: params.documentType,
276
+ country_code: params.countryCode,
277
+ device_info: params.deviceInfo,
278
+ };
279
+
280
+ logger.info('Full validation request', {
281
+ hasSessionId: !!this.currentSessionId,
282
+ sessionId: this.currentSessionId,
283
+ videoFramesCount: params.videoFrames.length,
284
+ hasFrontImage: !!params.frontIdImage,
285
+ hasBackImage: !!params.backIdImage,
286
+ frontImageLength: params.frontIdImage?.length || 0,
287
+ backImageLength: params.backIdImage?.length || 0,
288
+ averageFrameLength: params.videoFrames.length > 0
289
+ ? Math.round(params.videoFrames.reduce((sum, f) => sum + f.length, 0) / params.videoFrames.length)
290
+ : 0
291
+ });
292
+
268
293
  return this.request<FullValidationResponse>(
269
294
  '/api/v1/validate',
270
295
  'POST',
271
- {
272
- front_id_image: params.frontIdImage,
273
- back_id_image: params.backIdImage,
274
- video_frames: params.videoFrames,
275
- video_duration_ms: params.videoDurationMs,
276
- session_id: this.currentSessionId,
277
- challenges_completed: params.challengesCompleted || [],
278
- document_type: params.documentType,
279
- country_code: params.countryCode,
280
- device_info: params.deviceInfo,
281
- }
296
+ requestBody
282
297
  );
283
298
  }
284
299
 
@@ -359,6 +374,13 @@ export class BackendClient {
359
374
  ): Promise<T> {
360
375
  const url = `${this.config.apiEndpoint}${endpoint}`;
361
376
 
377
+ logger.info('Making backend request', {
378
+ url,
379
+ method,
380
+ hasBody: !!body,
381
+ bodySize: body ? JSON.stringify(body).length : 0
382
+ });
383
+
362
384
  const controller = new AbortController();
363
385
  const timeoutId = setTimeout(() => controller.abort(), this.config.timeout);
364
386
 
@@ -378,23 +400,60 @@ export class BackendClient {
378
400
  body: body ? JSON.stringify(body) : undefined,
379
401
  signal: controller.signal as RequestInit['signal'],
380
402
  });
403
+
404
+ logger.info('Backend response received', {
405
+ url,
406
+ status: response.status,
407
+ statusText: response.statusText,
408
+ ok: response.ok
409
+ });
381
410
 
382
411
  clearTimeout(timeoutId);
383
412
 
384
413
  if (!response.ok) {
385
- // Handle 413 Payload Too Large specifically
414
+ let errorText = '';
415
+ let errorData: Record<string, any> = {};
416
+
417
+ try {
418
+ errorText = await response.text();
419
+ if (errorText) {
420
+ try {
421
+ errorData = JSON.parse(errorText);
422
+ } catch {
423
+ errorData = { raw: errorText };
424
+ }
425
+ }
426
+ } catch (parseError) {
427
+ logger.warn('Could not parse error response', parseError);
428
+ }
429
+
430
+ const errorMessage = errorData?.error?.message ||
431
+ errorData?.detail ||
432
+ errorData?.message ||
433
+ errorData?.raw ||
434
+ `Request failed with status ${response.status}: ${response.statusText}`;
435
+
436
+ logger.error('Backend request failed', {
437
+ url,
438
+ method,
439
+ status: response.status,
440
+ statusText: response.statusText,
441
+ errorText: errorText.substring(0, 500),
442
+ errorData: JSON.stringify(errorData).substring(0, 500)
443
+ });
444
+
445
+ const error = new Error(errorMessage);
446
+ (error as any).status = response.status;
447
+ (error as any).statusText = response.statusText;
448
+ (error as any).errorData = errorData;
449
+
386
450
  if (response.status === 413) {
387
451
  throw new Error(
388
452
  `Payload too large (413). The request body exceeds the server's size limit. Try reducing the number of video frames or image sizes.`
389
453
  );
390
454
  }
391
455
 
392
- const errorData = await response.json().catch(() => ({})) as Record<string, any>;
393
- throw new Error(
394
- errorData?.error?.message ||
395
- errorData?.detail ||
396
- `Request failed with status ${response.status}`
397
- );
456
+ throw error;
398
457
  }
399
458
 
400
459
  return await response.json() as T;
@@ -402,10 +461,16 @@ export class BackendClient {
402
461
  clearTimeout(timeoutId);
403
462
 
404
463
  if (error.name === 'AbortError') {
464
+ logger.error('Request timeout', { url, method, timeout: this.config.timeout });
405
465
  throw new Error('Request timeout');
406
466
  }
407
467
 
408
- throw error;
468
+ if (error.message) {
469
+ throw error;
470
+ }
471
+
472
+ logger.error('Unexpected request error', { url, method, error });
473
+ throw new Error('Network request failed');
409
474
  }
410
475
  }
411
476
  }