@sekyro/web 0.1.0-rc.4 → 0.1.0-rc.6
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/CHANGELOG.md +30 -0
- package/README.md +44 -0
- package/dist/{capture-session-v3-uXJr1Wlm.d.ts → capture-session-v3-Okq0EQHG.d.ts} +9 -2
- package/dist/{capture-session-v3-DEInCOUg.d.cts → capture-session-v3-UQU_WjO2.d.cts} +9 -2
- package/dist/{chunk-TBANUT3X.js → chunk-R3SJQHYU.js} +296 -8
- package/dist/chunk-R3SJQHYU.js.map +1 -0
- package/dist/{chunk-EWRNPKTR.js → chunk-TG5IE552.js} +7 -2
- package/dist/{chunk-EWRNPKTR.js.map → chunk-TG5IE552.js.map} +1 -1
- package/dist/client/index.cjs.map +1 -1
- package/dist/client/index.d.cts +1 -1
- package/dist/client/index.d.ts +1 -1
- package/dist/core/index.cjs +6 -1
- package/dist/core/index.cjs.map +1 -1
- package/dist/core/index.d.cts +2 -2
- package/dist/core/index.d.ts +2 -2
- package/dist/core/index.js +1 -1
- package/dist/{create-verification-Dkb2tXuY.d.cts → create-verification-BKc9NFQj.d.cts} +92 -8
- package/dist/{create-verification-Ce1y5kJR.d.ts → create-verification-DjcMZHAQ.d.ts} +92 -8
- package/dist/{hosted-client-DWzCRYJK.d.cts → hosted-client-DJXq_CB9.d.cts} +29 -1
- package/dist/{hosted-client-DWzCRYJK.d.ts → hosted-client-DJXq_CB9.d.ts} +29 -1
- package/dist/index.cjs +341 -9
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +25 -3
- package/dist/index.d.ts +25 -3
- package/dist/index.js +61 -4
- package/dist/index.js.map +1 -1
- package/dist/internal/index.cjs +218 -7
- package/dist/internal/index.cjs.map +1 -1
- package/dist/internal/index.d.cts +4 -4
- package/dist/internal/index.d.ts +4 -4
- package/dist/internal/index.js +12 -2
- package/dist/internal/index.js.map +1 -1
- package/package.json +1 -1
- package/dist/chunk-TBANUT3X.js.map +0 -1
package/dist/index.d.cts
CHANGED
|
@@ -1,6 +1,28 @@
|
|
|
1
|
-
export { C as
|
|
1
|
+
export { C as CameraFacing, a as CaptureChannel, b as CaptureEngineId, c as CaptureError, d as CaptureErrorKind, e as CaptureState, f as CapturedArtifacts, D as DEFAULT_API_ORIGIN, G as GateHint, g as GateUpdate, L as LivenessAssetsStatus, h as LivenessCaptureEvents, i as LivenessCaptureHandle, j as LivenessCaptureOptions, k as LivenessStartOptions, P as PreloadLivenessAssetsOptions, R as ReasonCode, S as SdkFailureReason, V as Verification, l as VerificationEvents, m as VerificationLocale, n as VerificationOptions, o as VerificationResult, p as VerificationStatus, q as createLivenessCapture, r as createVerification, s as getLivenessAssetsStatus, t as preloadLivenessAssets, u as releaseLivenessAssets, v as subscribeLivenessAssets } from './create-verification-BKc9NFQj.cjs';
|
|
2
2
|
export { OpenHostedOptions, PopupBlocked, PopupHandle, SEKYRO_EVENTS, SekyroEvent, SekyroEventName, openHosted } from './popup/index.cjs';
|
|
3
3
|
export { HostedApiError, KNOWN_CODES, KnownCode, isKnownCode } from './client/index.cjs';
|
|
4
|
-
export { C as CheckReason, a as CheckState, b as CheckType, D as DocReason, F as FaceMatchReason, H as HostedOtpView, c as HostedSessionView, d as HostedStepView, L as LivenessReason, P as PhoneOtpReason,
|
|
5
|
-
import './capture-session-v3-DEInCOUg.cjs';
|
|
4
|
+
export { C as CheckReason, a as CheckState, b as CheckType, D as DocReason, F as FaceMatchReason, H as HostedOtpView, c as HostedSessionView, d as HostedStepView, e as HostedVoiceLocale, f as HostedVoiceView, L as LivenessReason, P as PhoneOtpReason, g as PopulationReason, S as SessionOutcome, h as SessionStatus } from './hosted-client-DJXq_CB9.cjs';
|
|
6
5
|
import './detect-worker-CKXHlXx9.cjs';
|
|
6
|
+
import './capture-session-v3-UQU_WjO2.cjs';
|
|
7
|
+
|
|
8
|
+
/** Camera permission as the Permissions API reports it; `'unknown'` where it cannot tell. */
|
|
9
|
+
type CameraPermissionState = "granted" | "prompt" | "denied" | "unknown";
|
|
10
|
+
/** One-shot camera permission read. */
|
|
11
|
+
declare function queryCameraPermission(): Promise<CameraPermissionState>;
|
|
12
|
+
/**
|
|
13
|
+
* Subscribe to camera-permission changes; returns the unsubscribe function.
|
|
14
|
+
* Unlike {@link subscribeLivenessAssets}, it DOES emit the current state first
|
|
15
|
+
* (as soon as the Permissions API answers — asynchronously, `'unknown'` where
|
|
16
|
+
* unsupported), then on every change. Not a `useSyncExternalStore` source:
|
|
17
|
+
* there is no synchronous snapshot — drive a `useState` from it.
|
|
18
|
+
*/
|
|
19
|
+
declare function subscribeCameraPermission(listener: (state: CameraPermissionState) => void): () => void;
|
|
20
|
+
/**
|
|
21
|
+
* Whether a front/back choice makes sense: phones and tablets (UA, incl. iPadOS's
|
|
22
|
+
* desktop UA) always have both; otherwise ≥ 2 `videoinput` devices. Before a
|
|
23
|
+
* permission was ever granted some desktops report a single placeholder — the
|
|
24
|
+
* in-capture switch remains available either way.
|
|
25
|
+
*/
|
|
26
|
+
declare function hasMultipleCameras(): Promise<boolean>;
|
|
27
|
+
|
|
28
|
+
export { type CameraPermissionState, hasMultipleCameras, queryCameraPermission, subscribeCameraPermission };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,28 @@
|
|
|
1
|
-
export { C as
|
|
1
|
+
export { C as CameraFacing, a as CaptureChannel, b as CaptureEngineId, c as CaptureError, d as CaptureErrorKind, e as CaptureState, f as CapturedArtifacts, D as DEFAULT_API_ORIGIN, G as GateHint, g as GateUpdate, L as LivenessAssetsStatus, h as LivenessCaptureEvents, i as LivenessCaptureHandle, j as LivenessCaptureOptions, k as LivenessStartOptions, P as PreloadLivenessAssetsOptions, R as ReasonCode, S as SdkFailureReason, V as Verification, l as VerificationEvents, m as VerificationLocale, n as VerificationOptions, o as VerificationResult, p as VerificationStatus, q as createLivenessCapture, r as createVerification, s as getLivenessAssetsStatus, t as preloadLivenessAssets, u as releaseLivenessAssets, v as subscribeLivenessAssets } from './create-verification-DjcMZHAQ.js';
|
|
2
2
|
export { OpenHostedOptions, PopupBlocked, PopupHandle, SEKYRO_EVENTS, SekyroEvent, SekyroEventName, openHosted } from './popup/index.js';
|
|
3
3
|
export { HostedApiError, KNOWN_CODES, KnownCode, isKnownCode } from './client/index.js';
|
|
4
|
-
export { C as CheckReason, a as CheckState, b as CheckType, D as DocReason, F as FaceMatchReason, H as HostedOtpView, c as HostedSessionView, d as HostedStepView, L as LivenessReason, P as PhoneOtpReason,
|
|
5
|
-
import './capture-session-v3-uXJr1Wlm.js';
|
|
4
|
+
export { C as CheckReason, a as CheckState, b as CheckType, D as DocReason, F as FaceMatchReason, H as HostedOtpView, c as HostedSessionView, d as HostedStepView, e as HostedVoiceLocale, f as HostedVoiceView, L as LivenessReason, P as PhoneOtpReason, g as PopulationReason, S as SessionOutcome, h as SessionStatus } from './hosted-client-DJXq_CB9.js';
|
|
6
5
|
import './detect-worker-CKXHlXx9.js';
|
|
6
|
+
import './capture-session-v3-Okq0EQHG.js';
|
|
7
|
+
|
|
8
|
+
/** Camera permission as the Permissions API reports it; `'unknown'` where it cannot tell. */
|
|
9
|
+
type CameraPermissionState = "granted" | "prompt" | "denied" | "unknown";
|
|
10
|
+
/** One-shot camera permission read. */
|
|
11
|
+
declare function queryCameraPermission(): Promise<CameraPermissionState>;
|
|
12
|
+
/**
|
|
13
|
+
* Subscribe to camera-permission changes; returns the unsubscribe function.
|
|
14
|
+
* Unlike {@link subscribeLivenessAssets}, it DOES emit the current state first
|
|
15
|
+
* (as soon as the Permissions API answers — asynchronously, `'unknown'` where
|
|
16
|
+
* unsupported), then on every change. Not a `useSyncExternalStore` source:
|
|
17
|
+
* there is no synchronous snapshot — drive a `useState` from it.
|
|
18
|
+
*/
|
|
19
|
+
declare function subscribeCameraPermission(listener: (state: CameraPermissionState) => void): () => void;
|
|
20
|
+
/**
|
|
21
|
+
* Whether a front/back choice makes sense: phones and tablets (UA, incl. iPadOS's
|
|
22
|
+
* desktop UA) always have both; otherwise ≥ 2 `videoinput` devices. Before a
|
|
23
|
+
* permission was ever granted some desktops report a single placeholder — the
|
|
24
|
+
* in-capture switch remains available either way.
|
|
25
|
+
*/
|
|
26
|
+
declare function hasMultipleCameras(): Promise<boolean>;
|
|
27
|
+
|
|
28
|
+
export { type CameraPermissionState, hasMultipleCameras, queryCameraPermission, subscribeCameraPermission };
|
package/dist/index.js
CHANGED
|
@@ -5,9 +5,13 @@ import {
|
|
|
5
5
|
import {
|
|
6
6
|
DEFAULT_API_ORIGIN,
|
|
7
7
|
createLivenessCapture,
|
|
8
|
-
createVerification
|
|
9
|
-
|
|
10
|
-
|
|
8
|
+
createVerification,
|
|
9
|
+
getLivenessAssetsStatus,
|
|
10
|
+
preloadLivenessAssets,
|
|
11
|
+
releaseLivenessAssets,
|
|
12
|
+
subscribeLivenessAssets
|
|
13
|
+
} from "./chunk-R3SJQHYU.js";
|
|
14
|
+
import "./chunk-TG5IE552.js";
|
|
11
15
|
import {
|
|
12
16
|
HostedApiError,
|
|
13
17
|
KNOWN_CODES,
|
|
@@ -15,6 +19,52 @@ import {
|
|
|
15
19
|
} from "./chunk-YVFF4Q4G.js";
|
|
16
20
|
import "./chunk-NWF46H7K.js";
|
|
17
21
|
import "./chunk-MWNFSNMP.js";
|
|
22
|
+
|
|
23
|
+
// src/capture/camera-probe.ts
|
|
24
|
+
async function permissionStatus() {
|
|
25
|
+
try {
|
|
26
|
+
if (typeof navigator === "undefined" || typeof navigator.permissions?.query !== "function") return null;
|
|
27
|
+
return await navigator.permissions.query({ name: "camera" });
|
|
28
|
+
} catch {
|
|
29
|
+
return null;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
function asState(state) {
|
|
33
|
+
return state === "granted" || state === "prompt" || state === "denied" ? state : "unknown";
|
|
34
|
+
}
|
|
35
|
+
async function queryCameraPermission() {
|
|
36
|
+
const status = await permissionStatus();
|
|
37
|
+
return status === null ? "unknown" : asState(status.state);
|
|
38
|
+
}
|
|
39
|
+
function subscribeCameraPermission(listener) {
|
|
40
|
+
let stopped = false;
|
|
41
|
+
let status = null;
|
|
42
|
+
const onChange = () => {
|
|
43
|
+
if (!stopped && status !== null) listener(asState(status.state));
|
|
44
|
+
};
|
|
45
|
+
void permissionStatus().then((resolved) => {
|
|
46
|
+
if (stopped) return;
|
|
47
|
+
status = resolved;
|
|
48
|
+
listener(resolved === null ? "unknown" : asState(resolved.state));
|
|
49
|
+
resolved?.addEventListener?.("change", onChange);
|
|
50
|
+
});
|
|
51
|
+
return () => {
|
|
52
|
+
stopped = true;
|
|
53
|
+
status?.removeEventListener?.("change", onChange);
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
async function hasMultipleCameras() {
|
|
57
|
+
if (typeof navigator === "undefined") return false;
|
|
58
|
+
const ua = String(navigator.userAgent ?? "");
|
|
59
|
+
if (/Android|iPhone|iPad|iPod/i.test(ua)) return true;
|
|
60
|
+
if (/Macintosh/.test(ua) && (navigator.maxTouchPoints ?? 0) > 1) return true;
|
|
61
|
+
try {
|
|
62
|
+
const devices = await navigator.mediaDevices?.enumerateDevices?.() ?? [];
|
|
63
|
+
return devices.filter((device) => device.kind === "videoinput").length >= 2;
|
|
64
|
+
} catch {
|
|
65
|
+
return false;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
18
68
|
export {
|
|
19
69
|
DEFAULT_API_ORIGIN,
|
|
20
70
|
HostedApiError,
|
|
@@ -22,7 +72,14 @@ export {
|
|
|
22
72
|
SEKYRO_EVENTS,
|
|
23
73
|
createLivenessCapture,
|
|
24
74
|
createVerification,
|
|
75
|
+
getLivenessAssetsStatus,
|
|
76
|
+
hasMultipleCameras,
|
|
25
77
|
isKnownCode,
|
|
26
|
-
openHosted
|
|
78
|
+
openHosted,
|
|
79
|
+
preloadLivenessAssets,
|
|
80
|
+
queryCameraPermission,
|
|
81
|
+
releaseLivenessAssets,
|
|
82
|
+
subscribeCameraPermission,
|
|
83
|
+
subscribeLivenessAssets
|
|
27
84
|
};
|
|
28
85
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/capture/camera-probe.ts"],"sourcesContent":["// Camera probes for pre-capture UI (spec D6, D7). Every function is SSR-safe and\n// never throws: a missing / throwing API (Safari < 16 on {name:'camera'},\n// Firefox) degrades to 'unknown' / false.\n\n/** Camera permission as the Permissions API reports it; `'unknown'` where it cannot tell. */\nexport type CameraPermissionState = \"granted\" | \"prompt\" | \"denied\" | \"unknown\";\n\nasync function permissionStatus(): Promise<PermissionStatus | null> {\n try {\n if (typeof navigator === \"undefined\" || typeof navigator.permissions?.query !== \"function\") return null;\n return await navigator.permissions.query({ name: \"camera\" as PermissionName });\n } catch {\n return null;\n }\n}\n\nfunction asState(state: string): CameraPermissionState {\n return state === \"granted\" || state === \"prompt\" || state === \"denied\" ? state : \"unknown\";\n}\n\n/** One-shot camera permission read. */\nexport async function queryCameraPermission(): Promise<CameraPermissionState> {\n const status = await permissionStatus();\n return status === null ? \"unknown\" : asState(status.state);\n}\n\n/**\n * Subscribe to camera-permission changes; returns the unsubscribe function.\n * Unlike {@link subscribeLivenessAssets}, it DOES emit the current state first\n * (as soon as the Permissions API answers — asynchronously, `'unknown'` where\n * unsupported), then on every change. Not a `useSyncExternalStore` source:\n * there is no synchronous snapshot — drive a `useState` from it.\n */\nexport function subscribeCameraPermission(listener: (state: CameraPermissionState) => void): () => void {\n let stopped = false;\n let status: PermissionStatus | null = null;\n const onChange = (): void => {\n if (!stopped && status !== null) listener(asState(status.state));\n };\n void permissionStatus().then((resolved) => {\n if (stopped) return;\n status = resolved;\n listener(resolved === null ? \"unknown\" : asState(resolved.state));\n resolved?.addEventListener?.(\"change\", onChange);\n });\n return () => {\n stopped = true;\n status?.removeEventListener?.(\"change\", onChange);\n };\n}\n\n/**\n * Whether a front/back choice makes sense: phones and tablets (UA, incl. iPadOS's\n * desktop UA) always have both; otherwise ≥ 2 `videoinput` devices. Before a\n * permission was ever granted some desktops report a single placeholder — the\n * in-capture switch remains available either way.\n */\nexport async function hasMultipleCameras(): Promise<boolean> {\n if (typeof navigator === \"undefined\") return false;\n const ua = String(navigator.userAgent ?? \"\");\n if (/Android|iPhone|iPad|iPod/i.test(ua)) return true;\n if (/Macintosh/.test(ua) && (navigator.maxTouchPoints ?? 0) > 1) return true;\n try {\n const devices = (await navigator.mediaDevices?.enumerateDevices?.()) ?? [];\n return devices.filter((device) => device.kind === \"videoinput\").length >= 2;\n } catch {\n return false;\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;AAOA,eAAe,mBAAqD;AAClE,MAAI;AACF,QAAI,OAAO,cAAc,eAAe,OAAO,UAAU,aAAa,UAAU,WAAY,QAAO;AACnG,WAAO,MAAM,UAAU,YAAY,MAAM,EAAE,MAAM,SAA2B,CAAC;AAAA,EAC/E,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,SAAS,QAAQ,OAAsC;AACrD,SAAO,UAAU,aAAa,UAAU,YAAY,UAAU,WAAW,QAAQ;AACnF;AAGA,eAAsB,wBAAwD;AAC5E,QAAM,SAAS,MAAM,iBAAiB;AACtC,SAAO,WAAW,OAAO,YAAY,QAAQ,OAAO,KAAK;AAC3D;AASO,SAAS,0BAA0B,UAA8D;AACtG,MAAI,UAAU;AACd,MAAI,SAAkC;AACtC,QAAM,WAAW,MAAY;AAC3B,QAAI,CAAC,WAAW,WAAW,KAAM,UAAS,QAAQ,OAAO,KAAK,CAAC;AAAA,EACjE;AACA,OAAK,iBAAiB,EAAE,KAAK,CAAC,aAAa;AACzC,QAAI,QAAS;AACb,aAAS;AACT,aAAS,aAAa,OAAO,YAAY,QAAQ,SAAS,KAAK,CAAC;AAChE,cAAU,mBAAmB,UAAU,QAAQ;AAAA,EACjD,CAAC;AACD,SAAO,MAAM;AACX,cAAU;AACV,YAAQ,sBAAsB,UAAU,QAAQ;AAAA,EAClD;AACF;AAQA,eAAsB,qBAAuC;AAC3D,MAAI,OAAO,cAAc,YAAa,QAAO;AAC7C,QAAM,KAAK,OAAO,UAAU,aAAa,EAAE;AAC3C,MAAI,4BAA4B,KAAK,EAAE,EAAG,QAAO;AACjD,MAAI,YAAY,KAAK,EAAE,MAAM,UAAU,kBAAkB,KAAK,EAAG,QAAO;AACxE,MAAI;AACF,UAAM,UAAW,MAAM,UAAU,cAAc,mBAAmB,KAAM,CAAC;AACzE,WAAO,QAAQ,OAAO,CAAC,WAAW,OAAO,SAAS,YAAY,EAAE,UAAU;AAAA,EAC5E,QAAQ;AACN,WAAO;AAAA,EACT;AACF;","names":[]}
|
package/dist/internal/index.cjs
CHANGED
|
@@ -1105,6 +1105,8 @@ __export(internal_exports, {
|
|
|
1105
1105
|
IN_CIRCLE_FACTOR: () => IN_CIRCLE_FACTOR,
|
|
1106
1106
|
MRZ_BAND_DEFAULTS: () => MRZ_BAND_DEFAULTS,
|
|
1107
1107
|
MR_DOC_CATALOG: () => MR_DOC_CATALOG,
|
|
1108
|
+
PRELOAD_BLAZE_INIT_TIMEOUT_MS: () => PRELOAD_BLAZE_INIT_TIMEOUT_MS,
|
|
1109
|
+
PRELOAD_BUDGET_MS: () => PRELOAD_BUDGET_MS,
|
|
1108
1110
|
PROCESSING_POLL_DELAY_MS: () => PROCESSING_POLL_DELAY_MS,
|
|
1109
1111
|
PROCESSING_POLL_MAX: () => PROCESSING_POLL_MAX,
|
|
1110
1112
|
REGISTRY_RETRY_DELAY_MS: () => REGISTRY_RETRY_DELAY_MS,
|
|
@@ -1129,14 +1131,17 @@ __export(internal_exports, {
|
|
|
1129
1131
|
mapGuidanceHint: () => mapGuidanceHint,
|
|
1130
1132
|
mapSessionResult: () => mapSessionResult,
|
|
1131
1133
|
mergeSessionView: () => mergeSessionView,
|
|
1134
|
+
preloadedDetectorFactory: () => preloadedDetectorFactory,
|
|
1132
1135
|
quadAreaFrac: () => quadAreaFrac,
|
|
1133
1136
|
quadBounds: () => quadBounds,
|
|
1134
1137
|
quadIou: () => quadIou,
|
|
1135
1138
|
quadTiltRatio: () => quadTiltRatio,
|
|
1136
1139
|
randomUuid: () => randomUuid,
|
|
1140
|
+
resetLivenessAssetsForTests: () => resetLivenessAssetsForTests,
|
|
1137
1141
|
resetTurnstileForTests: () => resetTurnstileForTests,
|
|
1138
1142
|
runLivenessFlow: () => runLivenessFlow,
|
|
1139
1143
|
runSubmission: () => runSubmission,
|
|
1144
|
+
setPreloadLoaderForTests: () => setPreloadLoaderForTests,
|
|
1140
1145
|
specularFraction: () => specularFraction,
|
|
1141
1146
|
stepOf: () => stepOf,
|
|
1142
1147
|
warmDocDetector: () => warmDocDetector
|
|
@@ -2707,10 +2712,15 @@ var CaptureSessionV3 = class {
|
|
|
2707
2712
|
handler(payload);
|
|
2708
2713
|
}
|
|
2709
2714
|
}
|
|
2710
|
-
async start() {
|
|
2715
|
+
async start(options = {}) {
|
|
2716
|
+
if (options.facingMode !== void 0) this.facing = options.facingMode;
|
|
2711
2717
|
this.attempt += 1;
|
|
2712
2718
|
await this.run(this.attempt);
|
|
2713
2719
|
}
|
|
2720
|
+
/** The camera the current/next attempt requests (start option, switchCamera toggles). */
|
|
2721
|
+
get facingMode() {
|
|
2722
|
+
return this.facing;
|
|
2723
|
+
}
|
|
2714
2724
|
/** Full reset + camera restart — the documented recovery path (v1 parity). */
|
|
2715
2725
|
retry() {
|
|
2716
2726
|
this.teardownAttempt();
|
|
@@ -3118,6 +3128,179 @@ function createEmitter() {
|
|
|
3118
3128
|
};
|
|
3119
3129
|
}
|
|
3120
3130
|
|
|
3131
|
+
// src/capture/preload.ts
|
|
3132
|
+
var PRELOAD_BLAZE_INIT_TIMEOUT_MS = 12e4;
|
|
3133
|
+
var PRELOAD_BUDGET_MS = 13e4;
|
|
3134
|
+
var REGISTRY_KEY = /* @__PURE__ */ Symbol.for("@sekyro/web.preload.v1");
|
|
3135
|
+
function registry() {
|
|
3136
|
+
const host = globalThis;
|
|
3137
|
+
host[REGISTRY_KEY] ?? (host[REGISTRY_KEY] = /* @__PURE__ */ new Map());
|
|
3138
|
+
return host[REGISTRY_KEY];
|
|
3139
|
+
}
|
|
3140
|
+
function normalizeBase(assetBaseUrl) {
|
|
3141
|
+
const base = (assetBaseUrl ?? DEFAULT_V3_ASSET_BASE_URL).replace(/\/+$/, "");
|
|
3142
|
+
return base === "" ? "/" : base;
|
|
3143
|
+
}
|
|
3144
|
+
function setStatus(entry, next) {
|
|
3145
|
+
if (entry.status === next) return;
|
|
3146
|
+
entry.status = next;
|
|
3147
|
+
for (const listener of [...entry.listeners]) listener(next);
|
|
3148
|
+
}
|
|
3149
|
+
var defaultLoader = (base) => createDetector({ preferred: ["blaze"], v3AssetBaseUrl: base, blazeInitTimeoutMs: PRELOAD_BLAZE_INIT_TIMEOUT_MS });
|
|
3150
|
+
var loader = defaultLoader;
|
|
3151
|
+
function setPreloadLoaderForTests(next) {
|
|
3152
|
+
loader = next ?? defaultLoader;
|
|
3153
|
+
}
|
|
3154
|
+
function resetLivenessAssetsForTests() {
|
|
3155
|
+
for (const entry of registry().values()) entry.detector?.destroy();
|
|
3156
|
+
registry().clear();
|
|
3157
|
+
loader = defaultLoader;
|
|
3158
|
+
}
|
|
3159
|
+
function begin(entry, base) {
|
|
3160
|
+
if ((entry.status === "loading" || entry.status === "ready") && entry.promise !== null) return entry.promise;
|
|
3161
|
+
setStatus(entry, "loading");
|
|
3162
|
+
const detectorPromise = new Promise((resolve) => resolve(loader(base)));
|
|
3163
|
+
entry.detectorPromise = detectorPromise;
|
|
3164
|
+
let timer;
|
|
3165
|
+
const budget = new Promise((_2, reject) => {
|
|
3166
|
+
timer = setTimeout(() => {
|
|
3167
|
+
detectorPromise.then((late) => late.destroy(), () => void 0);
|
|
3168
|
+
reject(new Error(`detector preload exceeded ${PRELOAD_BUDGET_MS} ms`));
|
|
3169
|
+
}, PRELOAD_BUDGET_MS);
|
|
3170
|
+
});
|
|
3171
|
+
const settled = Promise.race([detectorPromise, budget]).then(
|
|
3172
|
+
(detector) => {
|
|
3173
|
+
if (entry.detectorPromise !== detectorPromise) {
|
|
3174
|
+
detector.destroy();
|
|
3175
|
+
return entry.status;
|
|
3176
|
+
}
|
|
3177
|
+
entry.detector = detector;
|
|
3178
|
+
setStatus(entry, "ready");
|
|
3179
|
+
return "ready";
|
|
3180
|
+
},
|
|
3181
|
+
(err) => {
|
|
3182
|
+
if (entry.detectorPromise === detectorPromise) {
|
|
3183
|
+
entry.detectorPromise = null;
|
|
3184
|
+
entry.detector = null;
|
|
3185
|
+
setStatus(entry, "failed");
|
|
3186
|
+
console.warn("[@sekyro/web] face-detector preload failed:", err);
|
|
3187
|
+
}
|
|
3188
|
+
return entry.status;
|
|
3189
|
+
}
|
|
3190
|
+
);
|
|
3191
|
+
const promise = settled.finally(() => clearTimeout(timer));
|
|
3192
|
+
entry.promise = promise;
|
|
3193
|
+
entry.scheduled?.settle(promise);
|
|
3194
|
+
return promise;
|
|
3195
|
+
}
|
|
3196
|
+
function nonOwningView(shared) {
|
|
3197
|
+
return {
|
|
3198
|
+
get tier() {
|
|
3199
|
+
return shared.tier;
|
|
3200
|
+
},
|
|
3201
|
+
get fallbackReason() {
|
|
3202
|
+
return shared.fallbackReason;
|
|
3203
|
+
},
|
|
3204
|
+
detect: (...args) => shared.detect(...args),
|
|
3205
|
+
destroy: () => {
|
|
3206
|
+
}
|
|
3207
|
+
};
|
|
3208
|
+
}
|
|
3209
|
+
function preloadedDetectorFactory(assetBaseUrl) {
|
|
3210
|
+
const base = normalizeBase(assetBaseUrl);
|
|
3211
|
+
const entry = registry().get(base);
|
|
3212
|
+
if (entry === void 0 || entry.detector === null && entry.detectorPromise === null && entry.scheduled === null) {
|
|
3213
|
+
return void 0;
|
|
3214
|
+
}
|
|
3215
|
+
return async () => {
|
|
3216
|
+
if (entry.scheduled !== null) void begin(entry, base);
|
|
3217
|
+
let waitingOn = entry.promise;
|
|
3218
|
+
while (entry.detector === null && waitingOn !== null) {
|
|
3219
|
+
await waitingOn;
|
|
3220
|
+
if (entry.promise === waitingOn) break;
|
|
3221
|
+
waitingOn = entry.promise;
|
|
3222
|
+
}
|
|
3223
|
+
return entry.detector !== null ? nonOwningView(entry.detector) : createDetector({ v3AssetBaseUrl: base });
|
|
3224
|
+
};
|
|
3225
|
+
}
|
|
3226
|
+
|
|
3227
|
+
// src/capture/wake-lock.ts
|
|
3228
|
+
function wakeLockApi() {
|
|
3229
|
+
if (typeof navigator === "undefined" || !("wakeLock" in navigator)) return null;
|
|
3230
|
+
const api = navigator.wakeLock;
|
|
3231
|
+
return typeof api?.request === "function" ? api : null;
|
|
3232
|
+
}
|
|
3233
|
+
function isVisible() {
|
|
3234
|
+
return typeof document === "undefined" || document.visibilityState === "visible";
|
|
3235
|
+
}
|
|
3236
|
+
function releaseQuietly(sentinel) {
|
|
3237
|
+
try {
|
|
3238
|
+
void sentinel.release().catch(() => void 0);
|
|
3239
|
+
} catch {
|
|
3240
|
+
}
|
|
3241
|
+
}
|
|
3242
|
+
function createScreenWakeLock(options = {}) {
|
|
3243
|
+
if (options.enabled === false) return { setActive: () => void 0 };
|
|
3244
|
+
let wanted = false;
|
|
3245
|
+
let sentinel = null;
|
|
3246
|
+
let inFlight = false;
|
|
3247
|
+
let listening = false;
|
|
3248
|
+
const acquire = () => {
|
|
3249
|
+
if (!wanted || inFlight || sentinel !== null && !sentinel.released) return;
|
|
3250
|
+
const api = wakeLockApi();
|
|
3251
|
+
if (api === null || !isVisible()) return;
|
|
3252
|
+
let request;
|
|
3253
|
+
try {
|
|
3254
|
+
request = api.request("screen");
|
|
3255
|
+
} catch {
|
|
3256
|
+
return;
|
|
3257
|
+
}
|
|
3258
|
+
inFlight = true;
|
|
3259
|
+
request.then(
|
|
3260
|
+
(granted) => {
|
|
3261
|
+
inFlight = false;
|
|
3262
|
+
if (!wanted) {
|
|
3263
|
+
releaseQuietly(granted);
|
|
3264
|
+
return;
|
|
3265
|
+
}
|
|
3266
|
+
sentinel = granted;
|
|
3267
|
+
granted.addEventListener?.("release", () => {
|
|
3268
|
+
if (sentinel === granted) sentinel = null;
|
|
3269
|
+
});
|
|
3270
|
+
},
|
|
3271
|
+
() => {
|
|
3272
|
+
inFlight = false;
|
|
3273
|
+
}
|
|
3274
|
+
);
|
|
3275
|
+
};
|
|
3276
|
+
const onVisibilityChange = () => {
|
|
3277
|
+
if (isVisible()) acquire();
|
|
3278
|
+
};
|
|
3279
|
+
const listen = (on) => {
|
|
3280
|
+
if (typeof document === "undefined" || on === listening) return;
|
|
3281
|
+
listening = on;
|
|
3282
|
+
if (on) document.addEventListener("visibilitychange", onVisibilityChange);
|
|
3283
|
+
else document.removeEventListener("visibilitychange", onVisibilityChange);
|
|
3284
|
+
};
|
|
3285
|
+
return {
|
|
3286
|
+
setActive: (active) => {
|
|
3287
|
+
wanted = active;
|
|
3288
|
+
if (active) {
|
|
3289
|
+
if (wakeLockApi() === null) return;
|
|
3290
|
+
listen(true);
|
|
3291
|
+
acquire();
|
|
3292
|
+
return;
|
|
3293
|
+
}
|
|
3294
|
+
listen(false);
|
|
3295
|
+
if (sentinel !== null) {
|
|
3296
|
+
const held = sentinel;
|
|
3297
|
+
sentinel = null;
|
|
3298
|
+
releaseQuietly(held);
|
|
3299
|
+
}
|
|
3300
|
+
}
|
|
3301
|
+
};
|
|
3302
|
+
}
|
|
3303
|
+
|
|
3121
3304
|
// src/capture/create-liveness-capture.ts
|
|
3122
3305
|
function mapGuidanceHint(key) {
|
|
3123
3306
|
switch (key) {
|
|
@@ -3181,12 +3364,22 @@ function createLivenessCaptureInternal(options, internals = {}) {
|
|
|
3181
3364
|
const now = internals.now ?? (() => performance.now());
|
|
3182
3365
|
const emitter = createEmitter();
|
|
3183
3366
|
const degraded = !isMediaRecorderSupported();
|
|
3367
|
+
const hostSeams = internals.engineOptions;
|
|
3368
|
+
const preloadAware = hostSeams?.createDetector === void 0 && hostSeams?.createWorker === void 0 ? {
|
|
3369
|
+
createDetector: () => {
|
|
3370
|
+
const warmed = preloadedDetectorFactory(options.assetBaseUrl);
|
|
3371
|
+
return warmed !== void 0 ? warmed() : createDetector(
|
|
3372
|
+
options.assetBaseUrl !== void 0 ? { v3AssetBaseUrl: options.assetBaseUrl } : {}
|
|
3373
|
+
);
|
|
3374
|
+
}
|
|
3375
|
+
} : {};
|
|
3184
3376
|
const engineOptions = {
|
|
3185
3377
|
video: options.video,
|
|
3186
3378
|
mode: degraded ? "photo" : "clip",
|
|
3187
3379
|
...options.facing !== void 0 ? { facingMode: options.facing } : {},
|
|
3188
3380
|
...options.assetBaseUrl !== void 0 ? { v3AssetBaseUrl: options.assetBaseUrl } : {},
|
|
3189
|
-
...internals.engineOptions ?? {}
|
|
3381
|
+
...internals.engineOptions ?? {},
|
|
3382
|
+
...preloadAware
|
|
3190
3383
|
};
|
|
3191
3384
|
const engine = internals.createEngine?.(engineOptions) ?? new CaptureSessionV3(engineOptions);
|
|
3192
3385
|
let state = "idle";
|
|
@@ -3204,8 +3397,10 @@ function createLivenessCaptureInternal(options, internals = {}) {
|
|
|
3204
3397
|
frameHeight = options.video.videoHeight;
|
|
3205
3398
|
}
|
|
3206
3399
|
};
|
|
3400
|
+
const wakeLock = createScreenWakeLock({ enabled: options.keepScreenAwake !== false });
|
|
3207
3401
|
const setState = (next) => {
|
|
3208
3402
|
state = next;
|
|
3403
|
+
wakeLock.setActive(next === "starting" || next === "gating" || next === "recording");
|
|
3209
3404
|
emitter.emit("state", next);
|
|
3210
3405
|
};
|
|
3211
3406
|
const emitGate = () => emitter.emit("gate", { progress, hint, faceDetected });
|
|
@@ -3279,11 +3474,12 @@ function createLivenessCaptureInternal(options, internals = {}) {
|
|
|
3279
3474
|
return state;
|
|
3280
3475
|
},
|
|
3281
3476
|
on: (event, handler) => emitter.on(event, handler),
|
|
3282
|
-
start: () => engine.start(),
|
|
3477
|
+
start: (startOptions) => engine.start(startOptions?.facing !== void 0 ? { facingMode: startOptions.facing } : {}),
|
|
3283
3478
|
retry: () => engine.retry(),
|
|
3284
3479
|
switchCamera: () => engine.switchCamera(),
|
|
3285
3480
|
destroy: () => {
|
|
3286
3481
|
for (const unsubscribe of unsubscribes) unsubscribe();
|
|
3482
|
+
wakeLock.setActive(false);
|
|
3287
3483
|
engine.destroy();
|
|
3288
3484
|
emitter.clear();
|
|
3289
3485
|
}
|
|
@@ -3991,7 +4187,7 @@ function createVerificationInternal(options, internals) {
|
|
|
3991
4187
|
}
|
|
3992
4188
|
emitter.emit("result", result);
|
|
3993
4189
|
};
|
|
3994
|
-
let
|
|
4190
|
+
let registry2 = null;
|
|
3995
4191
|
let registryFailed = false;
|
|
3996
4192
|
let registryUnbound = false;
|
|
3997
4193
|
const submitRegistry = () => runSubmission(
|
|
@@ -4026,8 +4222,8 @@ function createVerificationInternal(options, internals) {
|
|
|
4026
4222
|
if (view !== null && isTerminalView(view)) emitResult(mapSessionResult(view, { autoRetry }));
|
|
4027
4223
|
};
|
|
4028
4224
|
const startRegistry = () => {
|
|
4029
|
-
|
|
4030
|
-
return
|
|
4225
|
+
registry2 ?? (registry2 = runRegistry());
|
|
4226
|
+
return registry2;
|
|
4031
4227
|
};
|
|
4032
4228
|
const getAttestation = async () => {
|
|
4033
4229
|
const current = await ensureView();
|
|
@@ -4142,7 +4338,7 @@ function createVerificationInternal(options, internals) {
|
|
|
4142
4338
|
return inner.state;
|
|
4143
4339
|
},
|
|
4144
4340
|
on: (event, handler) => inner.on(event, handler),
|
|
4145
|
-
start: () => inner.start(),
|
|
4341
|
+
start: (startOptions) => inner.start(startOptions),
|
|
4146
4342
|
retry: () => inner.retry(),
|
|
4147
4343
|
switchCamera: () => inner.switchCamera(),
|
|
4148
4344
|
destroy: () => {
|
|
@@ -4156,6 +4352,16 @@ function createVerificationInternal(options, internals) {
|
|
|
4156
4352
|
consent: () => ensureConsent(),
|
|
4157
4353
|
startRegistry,
|
|
4158
4354
|
liveness,
|
|
4355
|
+
voiceClips: async () => {
|
|
4356
|
+
if (destroyed) return null;
|
|
4357
|
+
try {
|
|
4358
|
+
const current = await ensureView();
|
|
4359
|
+
if (destroyed) return null;
|
|
4360
|
+
return current.voice ?? null;
|
|
4361
|
+
} catch {
|
|
4362
|
+
return null;
|
|
4363
|
+
}
|
|
4364
|
+
},
|
|
4159
4365
|
on: (event, handler) => emitter.on(event, handler),
|
|
4160
4366
|
destroy: () => {
|
|
4161
4367
|
destroyed = true;
|
|
@@ -4189,6 +4395,8 @@ function createVerificationInternal(options, internals) {
|
|
|
4189
4395
|
IN_CIRCLE_FACTOR,
|
|
4190
4396
|
MRZ_BAND_DEFAULTS,
|
|
4191
4397
|
MR_DOC_CATALOG,
|
|
4398
|
+
PRELOAD_BLAZE_INIT_TIMEOUT_MS,
|
|
4399
|
+
PRELOAD_BUDGET_MS,
|
|
4192
4400
|
PROCESSING_POLL_DELAY_MS,
|
|
4193
4401
|
PROCESSING_POLL_MAX,
|
|
4194
4402
|
REGISTRY_RETRY_DELAY_MS,
|
|
@@ -4213,14 +4421,17 @@ function createVerificationInternal(options, internals) {
|
|
|
4213
4421
|
mapGuidanceHint,
|
|
4214
4422
|
mapSessionResult,
|
|
4215
4423
|
mergeSessionView,
|
|
4424
|
+
preloadedDetectorFactory,
|
|
4216
4425
|
quadAreaFrac,
|
|
4217
4426
|
quadBounds,
|
|
4218
4427
|
quadIou,
|
|
4219
4428
|
quadTiltRatio,
|
|
4220
4429
|
randomUuid,
|
|
4430
|
+
resetLivenessAssetsForTests,
|
|
4221
4431
|
resetTurnstileForTests,
|
|
4222
4432
|
runLivenessFlow,
|
|
4223
4433
|
runSubmission,
|
|
4434
|
+
setPreloadLoaderForTests,
|
|
4224
4435
|
specularFraction,
|
|
4225
4436
|
stepOf,
|
|
4226
4437
|
warmDocDetector
|