@moveris/shared 3.4.0 → 3.6.1
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/README.md +2 -2
- package/dist/index.d.mts +5 -2
- package/dist/index.d.ts +5 -2
- package/dist/index.js +27 -10
- package/dist/index.mjs +27 -10
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -550,7 +550,7 @@ const status = getStatusMessage('capturing', DEFAULT_LOCALE);
|
|
|
550
550
|
| `camera_angle_low` | "Raise camera to eye level" | Camera below face (Y < 0.3) |
|
|
551
551
|
| `camera_angle_high` | "Lower camera to eye level" | Camera above face (Y > 0.7) |
|
|
552
552
|
| `camera_tilted` | "Hold camera level" | Device tilt > 15° (via transformation matrix, falls back to eye-corner landmarks) |
|
|
553
|
-
| `flat_lighting` | "Find better lighting" | Face-region dynamic range <
|
|
553
|
+
| `flat_lighting` | "Find better lighting" | Face-region dynamic range < 60 L-units — soft warning, capture continues |
|
|
554
554
|
|
|
555
555
|
---
|
|
556
556
|
|
|
@@ -683,7 +683,7 @@ const angleResult = detectCameraAngle(landmarks); // requires ≥153 landmarks
|
|
|
683
683
|
// Pass pre-sampled face-region pixels — use sampleFaceRegionPixels() in @moveris/react
|
|
684
684
|
import { analyzeDynamicRange } from '@moveris/shared';
|
|
685
685
|
const drResult = analyzeDynamicRange(rgbaPixels);
|
|
686
|
-
// { range: number (max L* − min L*), isLow: boolean (<
|
|
686
|
+
// { range: number (max L* − min L*), isLow: boolean (< 60) }
|
|
687
687
|
// Soft warning — do not use as a hard capture gate
|
|
688
688
|
```
|
|
689
689
|
|
package/dist/index.d.mts
CHANGED
|
@@ -161,8 +161,11 @@ interface HealthResponse {
|
|
|
161
161
|
dependencies?: Record<string, unknown>;
|
|
162
162
|
}
|
|
163
163
|
interface ErrorResponse {
|
|
164
|
-
|
|
164
|
+
errors?: Array<Record<string, string[]>>;
|
|
165
165
|
message: string;
|
|
166
|
+
success?: false;
|
|
167
|
+
data?: null;
|
|
168
|
+
error?: string;
|
|
166
169
|
required?: number;
|
|
167
170
|
received?: number;
|
|
168
171
|
}
|
|
@@ -341,7 +344,7 @@ declare const MAX_FACE_RATIO = 0.7;
|
|
|
341
344
|
declare const FACE_CROP_OUTPUT_SIZE = 224;
|
|
342
345
|
declare const MAX_FACE_PERCENTAGE_IN_CROP = 0.45;
|
|
343
346
|
declare const TARGET_FACE_PERCENTAGE_IN_CROP = 0.33;
|
|
344
|
-
declare const DYNAMIC_RANGE_WARNING_THRESHOLD =
|
|
347
|
+
declare const DYNAMIC_RANGE_WARNING_THRESHOLD = 60;
|
|
345
348
|
interface DynamicRangeAnalysis {
|
|
346
349
|
range: number;
|
|
347
350
|
isLow: boolean;
|
package/dist/index.d.ts
CHANGED
|
@@ -161,8 +161,11 @@ interface HealthResponse {
|
|
|
161
161
|
dependencies?: Record<string, unknown>;
|
|
162
162
|
}
|
|
163
163
|
interface ErrorResponse {
|
|
164
|
-
|
|
164
|
+
errors?: Array<Record<string, string[]>>;
|
|
165
165
|
message: string;
|
|
166
|
+
success?: false;
|
|
167
|
+
data?: null;
|
|
168
|
+
error?: string;
|
|
166
169
|
required?: number;
|
|
167
170
|
received?: number;
|
|
168
171
|
}
|
|
@@ -341,7 +344,7 @@ declare const MAX_FACE_RATIO = 0.7;
|
|
|
341
344
|
declare const FACE_CROP_OUTPUT_SIZE = 224;
|
|
342
345
|
declare const MAX_FACE_PERCENTAGE_IN_CROP = 0.45;
|
|
343
346
|
declare const TARGET_FACE_PERCENTAGE_IN_CROP = 0.33;
|
|
344
|
-
declare const DYNAMIC_RANGE_WARNING_THRESHOLD =
|
|
347
|
+
declare const DYNAMIC_RANGE_WARNING_THRESHOLD = 60;
|
|
345
348
|
interface DynamicRangeAnalysis {
|
|
346
349
|
range: number;
|
|
347
350
|
isLow: boolean;
|
package/dist/index.js
CHANGED
|
@@ -342,7 +342,8 @@ var LivenessClient = class _LivenessClient {
|
|
|
342
342
|
if (!response.ok) {
|
|
343
343
|
throw await this.parseErrorResponse(response);
|
|
344
344
|
}
|
|
345
|
-
const
|
|
345
|
+
const json = await response.json();
|
|
346
|
+
const data = "data" in json && "success" in json ? json.data : json;
|
|
346
347
|
return { data, headers: response.headers };
|
|
347
348
|
} catch (error) {
|
|
348
349
|
clearTimeout(timeoutId);
|
|
@@ -362,11 +363,14 @@ var LivenessClient = class _LivenessClient {
|
|
|
362
363
|
/**
|
|
363
364
|
* Parse an error response body, handling both JSON and non-JSON bodies.
|
|
364
365
|
*
|
|
365
|
-
*
|
|
366
|
+
* Handles the new v2 envelope error format:
|
|
367
|
+
* ```json
|
|
368
|
+
* { "data": null, "success": false, "message": "...", "errors": [{ "error_code": ["detail"] }] }
|
|
369
|
+
* ```
|
|
370
|
+
* Falls back to the legacy format:
|
|
366
371
|
* ```json
|
|
367
372
|
* { "error": "http_error", "message": "{'error': 'session_expired', ...}" }
|
|
368
373
|
* ```
|
|
369
|
-
* This method unwraps such envelopes to extract the real error code.
|
|
370
374
|
*/
|
|
371
375
|
async parseErrorResponse(response) {
|
|
372
376
|
const status = response.status;
|
|
@@ -377,16 +381,29 @@ var LivenessClient = class _LivenessClient {
|
|
|
377
381
|
return new LivenessApiError(`Request failed with status ${status}`, "server_error", status);
|
|
378
382
|
}
|
|
379
383
|
try {
|
|
380
|
-
const
|
|
381
|
-
if (
|
|
382
|
-
const
|
|
383
|
-
|
|
384
|
+
const json = JSON.parse(body);
|
|
385
|
+
if (Array.isArray(json.errors) && json.errors.length > 0) {
|
|
386
|
+
const errorEntry = json.errors[0];
|
|
387
|
+
if (errorEntry) {
|
|
388
|
+
const errorCode = Object.keys(errorEntry)[0] ?? "server_error";
|
|
389
|
+
const msgs = errorEntry[errorCode];
|
|
390
|
+
const errorMessage = Array.isArray(msgs) && msgs.length > 0 ? msgs[0] : void 0;
|
|
391
|
+
return new LivenessApiError(
|
|
392
|
+
errorMessage ?? json.message ?? `Request failed (${errorCode})`,
|
|
393
|
+
errorCode,
|
|
394
|
+
status
|
|
395
|
+
);
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
if (json.error) {
|
|
399
|
+
const realCode = _LivenessClient.unwrapErrorCode(json.error, json.message);
|
|
400
|
+
const realMessage = _LivenessClient.unwrapErrorMessage(json.message);
|
|
384
401
|
return new LivenessApiError(
|
|
385
402
|
realMessage ?? `Request failed (${realCode})`,
|
|
386
403
|
realCode,
|
|
387
404
|
status,
|
|
388
|
-
|
|
389
|
-
|
|
405
|
+
json.required,
|
|
406
|
+
json.received
|
|
390
407
|
);
|
|
391
408
|
}
|
|
392
409
|
} catch {
|
|
@@ -1657,7 +1674,7 @@ var MAX_FACE_RATIO = 0.7;
|
|
|
1657
1674
|
var FACE_CROP_OUTPUT_SIZE = 224;
|
|
1658
1675
|
var MAX_FACE_PERCENTAGE_IN_CROP = 0.45;
|
|
1659
1676
|
var TARGET_FACE_PERCENTAGE_IN_CROP = 0.33;
|
|
1660
|
-
var DYNAMIC_RANGE_WARNING_THRESHOLD =
|
|
1677
|
+
var DYNAMIC_RANGE_WARNING_THRESHOLD = 60;
|
|
1661
1678
|
function srgbToLinear(c) {
|
|
1662
1679
|
const n = c / 255;
|
|
1663
1680
|
return n <= 0.04045 ? n / 12.92 : Math.pow((n + 0.055) / 1.055, 2.4);
|
package/dist/index.mjs
CHANGED
|
@@ -198,7 +198,8 @@ var LivenessClient = class _LivenessClient {
|
|
|
198
198
|
if (!response.ok) {
|
|
199
199
|
throw await this.parseErrorResponse(response);
|
|
200
200
|
}
|
|
201
|
-
const
|
|
201
|
+
const json = await response.json();
|
|
202
|
+
const data = "data" in json && "success" in json ? json.data : json;
|
|
202
203
|
return { data, headers: response.headers };
|
|
203
204
|
} catch (error) {
|
|
204
205
|
clearTimeout(timeoutId);
|
|
@@ -218,11 +219,14 @@ var LivenessClient = class _LivenessClient {
|
|
|
218
219
|
/**
|
|
219
220
|
* Parse an error response body, handling both JSON and non-JSON bodies.
|
|
220
221
|
*
|
|
221
|
-
*
|
|
222
|
+
* Handles the new v2 envelope error format:
|
|
223
|
+
* ```json
|
|
224
|
+
* { "data": null, "success": false, "message": "...", "errors": [{ "error_code": ["detail"] }] }
|
|
225
|
+
* ```
|
|
226
|
+
* Falls back to the legacy format:
|
|
222
227
|
* ```json
|
|
223
228
|
* { "error": "http_error", "message": "{'error': 'session_expired', ...}" }
|
|
224
229
|
* ```
|
|
225
|
-
* This method unwraps such envelopes to extract the real error code.
|
|
226
230
|
*/
|
|
227
231
|
async parseErrorResponse(response) {
|
|
228
232
|
const status = response.status;
|
|
@@ -233,16 +237,29 @@ var LivenessClient = class _LivenessClient {
|
|
|
233
237
|
return new LivenessApiError(`Request failed with status ${status}`, "server_error", status);
|
|
234
238
|
}
|
|
235
239
|
try {
|
|
236
|
-
const
|
|
237
|
-
if (
|
|
238
|
-
const
|
|
239
|
-
|
|
240
|
+
const json = JSON.parse(body);
|
|
241
|
+
if (Array.isArray(json.errors) && json.errors.length > 0) {
|
|
242
|
+
const errorEntry = json.errors[0];
|
|
243
|
+
if (errorEntry) {
|
|
244
|
+
const errorCode = Object.keys(errorEntry)[0] ?? "server_error";
|
|
245
|
+
const msgs = errorEntry[errorCode];
|
|
246
|
+
const errorMessage = Array.isArray(msgs) && msgs.length > 0 ? msgs[0] : void 0;
|
|
247
|
+
return new LivenessApiError(
|
|
248
|
+
errorMessage ?? json.message ?? `Request failed (${errorCode})`,
|
|
249
|
+
errorCode,
|
|
250
|
+
status
|
|
251
|
+
);
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
if (json.error) {
|
|
255
|
+
const realCode = _LivenessClient.unwrapErrorCode(json.error, json.message);
|
|
256
|
+
const realMessage = _LivenessClient.unwrapErrorMessage(json.message);
|
|
240
257
|
return new LivenessApiError(
|
|
241
258
|
realMessage ?? `Request failed (${realCode})`,
|
|
242
259
|
realCode,
|
|
243
260
|
status,
|
|
244
|
-
|
|
245
|
-
|
|
261
|
+
json.required,
|
|
262
|
+
json.received
|
|
246
263
|
);
|
|
247
264
|
}
|
|
248
265
|
} catch {
|
|
@@ -1513,7 +1530,7 @@ var MAX_FACE_RATIO = 0.7;
|
|
|
1513
1530
|
var FACE_CROP_OUTPUT_SIZE = 224;
|
|
1514
1531
|
var MAX_FACE_PERCENTAGE_IN_CROP = 0.45;
|
|
1515
1532
|
var TARGET_FACE_PERCENTAGE_IN_CROP = 0.33;
|
|
1516
|
-
var DYNAMIC_RANGE_WARNING_THRESHOLD =
|
|
1533
|
+
var DYNAMIC_RANGE_WARNING_THRESHOLD = 60;
|
|
1517
1534
|
function srgbToLinear(c) {
|
|
1518
1535
|
const n = c / 255;
|
|
1519
1536
|
return n <= 0.04045 ? n / 12.92 : Math.pow((n + 0.055) / 1.055, 2.4);
|