smartcomply-web-sdk 1.0.77 → 1.0.79
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/camera/FaceDetector.d.ts.map +1 -1
- package/dist/camera/FaceDetector.js +42 -17
- package/dist/camera/FaceDetector.js.map +1 -1
- package/dist/client/Smartcomply.d.ts +10 -0
- package/dist/client/Smartcomply.d.ts.map +1 -1
- package/dist/client/Smartcomply.js +12 -0
- package/dist/client/Smartcomply.js.map +1 -1
- package/dist/esm/camera/FaceDetector.d.ts.map +1 -1
- package/dist/esm/camera/FaceDetector.js +42 -17
- package/dist/esm/camera/FaceDetector.js.map +1 -1
- package/dist/esm/client/Smartcomply.d.ts +10 -0
- package/dist/esm/client/Smartcomply.d.ts.map +1 -1
- package/dist/esm/client/Smartcomply.js +12 -0
- package/dist/esm/client/Smartcomply.js.map +1 -1
- package/dist/esm/flow/SmartComplyFlow.d.ts +1 -0
- package/dist/esm/flow/SmartComplyFlow.d.ts.map +1 -1
- package/dist/esm/flow/SmartComplyFlow.js +27 -0
- package/dist/esm/flow/SmartComplyFlow.js.map +1 -1
- package/dist/esm/modules/liveness/liveness.d.ts.map +1 -1
- package/dist/esm/modules/liveness/liveness.js +17 -1
- package/dist/esm/modules/liveness/liveness.js.map +1 -1
- package/dist/esm/utils/logger.d.ts +7 -0
- package/dist/esm/utils/logger.d.ts.map +1 -1
- package/dist/esm/utils/logger.js +9 -0
- package/dist/esm/utils/logger.js.map +1 -1
- package/dist/flow/SmartComplyFlow.d.ts +1 -0
- package/dist/flow/SmartComplyFlow.d.ts.map +1 -1
- package/dist/flow/SmartComplyFlow.js +27 -0
- package/dist/flow/SmartComplyFlow.js.map +1 -1
- package/dist/modules/liveness/liveness.d.ts.map +1 -1
- package/dist/modules/liveness/liveness.js +17 -1
- package/dist/modules/liveness/liveness.js.map +1 -1
- package/dist/smartcomply.browser.js +103 -25
- package/dist/smartcomply.browser.js.map +3 -3
- package/dist/utils/logger.d.ts +7 -0
- package/dist/utils/logger.d.ts.map +1 -1
- package/dist/utils/logger.js +9 -0
- package/dist/utils/logger.js.map +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FaceDetector.d.ts","sourceRoot":"","sources":["../../src/camera/FaceDetector.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"FaceDetector.d.ts","sourceRoot":"","sources":["../../src/camera/FaceDetector.ts"],"names":[],"mappings":"AA4CA,MAAM,WAAW,mBAAmB;IAClC,YAAY,EAAE,OAAO,CAAC;IACtB,WAAW,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,eAAe,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;CAClC;AAED,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,UAAU,CAA+B;IAE3C,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAwC3B,MAAM,CAAC,KAAK,EAAE,gBAAgB,EAAE,SAAS,EAAE,MAAM,GAAG,mBAAmB;IA+BvE,OAAO,IAAI,IAAI;CAMhB"}
|
|
@@ -2,39 +2,64 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.FaceDetectorEngine = void 0;
|
|
4
4
|
const tasks_vision_1 = require("@mediapipe/tasks-vision");
|
|
5
|
-
|
|
6
|
-
|
|
5
|
+
// Pinned to the exact version in package.json ("@mediapipe/tasks-vision":
|
|
6
|
+
// "^0.10.32"). This MUST stay in sync with that dependency — using
|
|
7
|
+
// "@latest" here let jsDelivr silently swap in a newer WASM build than the
|
|
8
|
+
// JS API this SDK was built/tested against, breaking face detection for
|
|
9
|
+
// every user at once with no code change on our side. Bump both together.
|
|
10
|
+
const MEDIAPIPE_VERSION = "0.10.32";
|
|
11
|
+
const WASM_CDN = `https://cdn.jsdelivr.net/npm/@mediapipe/tasks-vision@${MEDIAPIPE_VERSION}/wasm`;
|
|
12
|
+
// Also pinned (was "/latest/") so a model update can't shift blendshape
|
|
13
|
+
// output out from under ActionDetector's calibrated thresholds unannounced.
|
|
14
|
+
const MODEL_URL = "https://storage.googleapis.com/mediapipe-models/face_landmarker/face_landmarker/float16/1/face_landmarker.task";
|
|
7
15
|
// Module-level cache — survives component remounts and retries within the same page session.
|
|
8
16
|
// First init fetches ~8MB total (WASM + model); subsequent inits reuse the cache instantly.
|
|
9
|
-
|
|
10
|
-
|
|
17
|
+
// Cached as in-flight PROMISES (not resolved values) so concurrent init() calls
|
|
18
|
+
// (e.g. parallel calls from two liveness attempts, or a fast retry) share one
|
|
19
|
+
// fetch instead of racing duplicate downloads — and so a failed attempt
|
|
20
|
+
// (rejected promise) doesn't get treated as "cached" and reused forever.
|
|
21
|
+
let _visionPromise = null;
|
|
22
|
+
let _modelBufferPromise = null;
|
|
23
|
+
/** Max time to wait for the WASM runtime / model download before giving up. */
|
|
24
|
+
const INIT_TIMEOUT_MS = 20000;
|
|
25
|
+
function withTimeout(promise, ms, label) {
|
|
26
|
+
return new Promise((resolve, reject) => {
|
|
27
|
+
const timer = setTimeout(() => reject(new Error(`${label} timed out. Please check your connection and try again.`)), ms);
|
|
28
|
+
promise.then((value) => { clearTimeout(timer); resolve(value); }, (err) => { clearTimeout(timer); reject(err); });
|
|
29
|
+
});
|
|
30
|
+
}
|
|
11
31
|
class FaceDetectorEngine {
|
|
12
32
|
constructor() {
|
|
13
33
|
this.landmarker = null;
|
|
14
34
|
}
|
|
15
35
|
async init() {
|
|
16
|
-
// Reuse WASM fileset — avoids re-fetching
|
|
17
|
-
|
|
18
|
-
|
|
36
|
+
// Reuse (or join) the in-flight WASM fileset load — avoids re-fetching
|
|
37
|
+
// ~3MB on retry/remount, and avoids kicking off a second parallel fetch
|
|
38
|
+
// if init() is called again before the first finishes.
|
|
39
|
+
if (!_visionPromise) {
|
|
40
|
+
_visionPromise = tasks_vision_1.FilesetResolver.forVisionTasks(WASM_CDN);
|
|
41
|
+
_visionPromise.catch(() => { _visionPromise = null; }); // don't cache a failure
|
|
19
42
|
}
|
|
20
|
-
// Reuse
|
|
21
|
-
if (!
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
43
|
+
// Reuse (or join) the in-flight model download — same reasoning.
|
|
44
|
+
if (!_modelBufferPromise) {
|
|
45
|
+
_modelBufferPromise = fetch(MODEL_URL).then((res) => {
|
|
46
|
+
if (!res.ok)
|
|
47
|
+
throw new Error(`Failed to download face model (${res.status})`);
|
|
48
|
+
return res.arrayBuffer();
|
|
49
|
+
});
|
|
50
|
+
_modelBufferPromise.catch(() => { _modelBufferPromise = null; }); // don't cache a failure
|
|
27
51
|
}
|
|
28
|
-
|
|
52
|
+
const [vision, modelBuffer] = await withTimeout(Promise.all([_visionPromise, _modelBufferPromise]), INIT_TIMEOUT_MS, "Face detection setup");
|
|
53
|
+
this.landmarker = await withTimeout(tasks_vision_1.FaceLandmarker.createFromOptions(vision, {
|
|
29
54
|
baseOptions: {
|
|
30
55
|
// Pass a copy — MediaPipe takes ownership of the buffer
|
|
31
|
-
modelAssetBuffer: new Uint8Array(
|
|
56
|
+
modelAssetBuffer: new Uint8Array(modelBuffer.slice(0)),
|
|
32
57
|
},
|
|
33
58
|
runningMode: "VIDEO",
|
|
34
59
|
outputFaceBlendshapes: true,
|
|
35
60
|
outputFacialTransformationMatrixes: true,
|
|
36
61
|
numFaces: 1,
|
|
37
|
-
});
|
|
62
|
+
}), INIT_TIMEOUT_MS, "Face detection setup");
|
|
38
63
|
}
|
|
39
64
|
detect(video, timestamp) {
|
|
40
65
|
if (!this.landmarker) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FaceDetector.js","sourceRoot":"","sources":["../../src/camera/FaceDetector.ts"],"names":[],"mappings":";;;AAAA,0DAIiC;AAEjC,MAAM,QAAQ,GACZ,
|
|
1
|
+
{"version":3,"file":"FaceDetector.js","sourceRoot":"","sources":["../../src/camera/FaceDetector.ts"],"names":[],"mappings":"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"}
|
|
@@ -12,6 +12,16 @@ import { SessionResponse, SDKInitConfig } from "../types/onboarding";
|
|
|
12
12
|
* // ... use sdk.onboarding and sdk.liveness modules
|
|
13
13
|
*/
|
|
14
14
|
export declare class SmartComply {
|
|
15
|
+
/**
|
|
16
|
+
* Package version, hardcoded to match package.json — bump this alongside
|
|
17
|
+
* every version bump there (same manual-sync convention already used for
|
|
18
|
+
* MEDIAPIPE_VERSION in camera/FaceDetector.ts). Exists so a client's
|
|
19
|
+
* running version can be confirmed directly (SmartComply.VERSION, or the
|
|
20
|
+
* console log on construction below) instead of trusting that whatever
|
|
21
|
+
* CDN tag they installed with (e.g. @1, which floats to the latest
|
|
22
|
+
* matching release) actually resolved to the version they expect.
|
|
23
|
+
*/
|
|
24
|
+
static readonly VERSION = "1.0.79";
|
|
15
25
|
private http;
|
|
16
26
|
private clientId;
|
|
17
27
|
private _sessionToken;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Smartcomply.d.ts","sourceRoot":"","sources":["../../src/client/Smartcomply.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAErC,OAAO,EAAE,gBAAgB,EAAE,MAAM,kCAAkC,CAAC;AACpE,OAAO,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;
|
|
1
|
+
{"version":3,"file":"Smartcomply.d.ts","sourceRoot":"","sources":["../../src/client/Smartcomply.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAErC,OAAO,EAAE,gBAAgB,EAAE,MAAM,kCAAkC,CAAC;AACpE,OAAO,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAE9D,OAAO,EACL,eAAe,EACf,aAAa,EACd,MAAM,qBAAqB,CAAC;AAE7B;;;;;;;;GAQG;AACH,qBAAa,WAAW;IACtB;;;;;;;;OAQG;IACH,MAAM,CAAC,QAAQ,CAAC,OAAO,YAAY;IAEnC,OAAO,CAAC,IAAI,CAAa;IACzB,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,aAAa,CAAuB;IAC5C,OAAO,CAAC,iBAAiB,CAAuB;IAChD,OAAO,CAAC,UAAU,CAA8B;IAEzC,UAAU,EAAE,gBAAgB,CAAC;IAC7B,QAAQ,EAAE,cAAc,CAAC;gBAEpB,MAAM,EAAE,SAAS;IAiB7B,sDAAsD;IACtD,IAAI,YAAY,IAAI,MAAM,GAAG,IAAI,CAEhC;IAED,uCAAuC;IACvC,IAAI,gBAAgB,IAAI,MAAM,GAAG,IAAI,CAEpC;IAED,gFAAgF;IAChF,IAAI,SAAS,IAAI,aAAa,GAAG,IAAI,CAEpC;IAED;;;;;;;;OAQG;IACG,aAAa,IAAI,OAAO,CAAC,eAAe,CAAC;IAgB/C;;;;;;;;OAQG;IACG,gBAAgB,IAAI,OAAO,CAAC,aAAa,CAAC;CASjD"}
|
|
@@ -4,6 +4,7 @@ exports.SmartComply = void 0;
|
|
|
4
4
|
const HttpClient_1 = require("./HttpClient");
|
|
5
5
|
const onboarding_1 = require("../modules/onboarding/onboarding");
|
|
6
6
|
const liveness_1 = require("../modules/liveness/liveness");
|
|
7
|
+
const logger_1 = require("../utils/logger");
|
|
7
8
|
/**
|
|
8
9
|
* SmartComply SDK — main entry point.
|
|
9
10
|
*
|
|
@@ -28,6 +29,7 @@ class SmartComply {
|
|
|
28
29
|
this.http = new HttpClient_1.HttpClient(config);
|
|
29
30
|
this.onboarding = new onboarding_1.OnboardingModule(this.http);
|
|
30
31
|
this.liveness = new liveness_1.LivenessModule(this.http);
|
|
32
|
+
logger_1.SDKLogger.always(`v${SmartComply.VERSION}`);
|
|
31
33
|
}
|
|
32
34
|
/** Current session token (null if not created yet) */
|
|
33
35
|
get sessionToken() {
|
|
@@ -74,4 +76,14 @@ class SmartComply {
|
|
|
74
76
|
}
|
|
75
77
|
}
|
|
76
78
|
exports.SmartComply = SmartComply;
|
|
79
|
+
/**
|
|
80
|
+
* Package version, hardcoded to match package.json — bump this alongside
|
|
81
|
+
* every version bump there (same manual-sync convention already used for
|
|
82
|
+
* MEDIAPIPE_VERSION in camera/FaceDetector.ts). Exists so a client's
|
|
83
|
+
* running version can be confirmed directly (SmartComply.VERSION, or the
|
|
84
|
+
* console log on construction below) instead of trusting that whatever
|
|
85
|
+
* CDN tag they installed with (e.g. @1, which floats to the latest
|
|
86
|
+
* matching release) actually resolved to the version they expect.
|
|
87
|
+
*/
|
|
88
|
+
SmartComply.VERSION = "1.0.79";
|
|
77
89
|
//# sourceMappingURL=Smartcomply.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Smartcomply.js","sourceRoot":"","sources":["../../src/client/Smartcomply.ts"],"names":[],"mappings":";;;AACA,6CAA0C;AAC1C,iEAAoE;AACpE,2DAA8D;
|
|
1
|
+
{"version":3,"file":"Smartcomply.js","sourceRoot":"","sources":["../../src/client/Smartcomply.ts"],"names":[],"mappings":";;;AACA,6CAA0C;AAC1C,iEAAoE;AACpE,2DAA8D;AAC9D,4CAA4C;AAM5C;;;;;;;;GAQG;AACH,MAAa,WAAW;IAqBtB,YAAY,MAAiB;QAPrB,kBAAa,GAAkB,IAAI,CAAC;QACpC,sBAAiB,GAAkB,IAAI,CAAC;QACxC,eAAU,GAAyB,IAAI,CAAC;QAM9C,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC;YACnB,MAAM,IAAI,KAAK,CAAC,iCAAiC,CAAC,CAAC;QACrD,CAAC;QACD,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC;YACrB,MAAM,IAAI,KAAK,CAAC,+DAA+D,CAAC,CAAC;QACnF,CAAC;QAED,IAAI,CAAC,QAAQ,GAAG,MAAM,CAAC,QAAQ,CAAC;QAChC,IAAI,CAAC,IAAI,GAAG,IAAI,uBAAU,CAAC,MAAM,CAAC,CAAC;QAEnC,IAAI,CAAC,UAAU,GAAG,IAAI,6BAAgB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAClD,IAAI,CAAC,QAAQ,GAAG,IAAI,yBAAc,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAE9C,kBAAS,CAAC,MAAM,CAAC,IAAI,WAAW,CAAC,OAAO,EAAE,CAAC,CAAC;IAC9C,CAAC;IAED,sDAAsD;IACtD,IAAI,YAAY;QACd,OAAO,IAAI,CAAC,aAAa,CAAC;IAC5B,CAAC;IAED,uCAAuC;IACvC,IAAI,gBAAgB;QAClB,OAAO,IAAI,CAAC,iBAAiB,CAAC;IAChC,CAAC;IAED,gFAAgF;IAChF,IAAI,SAAS;QACX,OAAO,IAAI,CAAC,UAAU,CAAC;IACzB,CAAC;IAED;;;;;;;;OAQG;IACH,KAAK,CAAC,aAAa;QACjB,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,OAAO,CACtC,MAAM,EACN,qBAAqB,EACrB,EAAE,SAAS,EAAE,IAAI,CAAC,QAAQ,EAAE,CAC7B,CAAC;QAEF,IAAI,CAAC,aAAa,GAAG,QAAQ,CAAC,KAAK,CAAC;QACpC,IAAI,CAAC,iBAAiB,GAAG,QAAQ,CAAC,UAAU,CAAC;QAE7C,mEAAmE;QACnE,IAAI,CAAC,IAAI,CAAC,eAAe,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;QAE1C,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED;;;;;;;;OAQG;IACH,KAAK,CAAC,gBAAgB;QACpB,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,cAAc,CAC3C,KAAK,EACL,iBAAiB,CAClB,CAAC;QAEF,IAAI,CAAC,UAAU,GAAG,MAAM,CAAC;QACzB,OAAO,MAAM,CAAC;IAChB,CAAC;;AA/FH,kCAgGC;AA/FC;;;;;;;;GAQG;AACa,mBAAO,GAAG,QAAQ,AAAX,CAAY"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FaceDetector.d.ts","sourceRoot":"","sources":["../../../src/camera/FaceDetector.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"FaceDetector.d.ts","sourceRoot":"","sources":["../../../src/camera/FaceDetector.ts"],"names":[],"mappings":"AA4CA,MAAM,WAAW,mBAAmB;IAClC,YAAY,EAAE,OAAO,CAAC;IACtB,WAAW,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,eAAe,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;CAClC;AAED,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,UAAU,CAA+B;IAE3C,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAwC3B,MAAM,CAAC,KAAK,EAAE,gBAAgB,EAAE,SAAS,EAAE,MAAM,GAAG,mBAAmB;IA+BvE,OAAO,IAAI,IAAI;CAMhB"}
|
|
@@ -1,37 +1,62 @@
|
|
|
1
1
|
import { FilesetResolver, FaceLandmarker, } from "@mediapipe/tasks-vision";
|
|
2
|
-
|
|
3
|
-
|
|
2
|
+
// Pinned to the exact version in package.json ("@mediapipe/tasks-vision":
|
|
3
|
+
// "^0.10.32"). This MUST stay in sync with that dependency — using
|
|
4
|
+
// "@latest" here let jsDelivr silently swap in a newer WASM build than the
|
|
5
|
+
// JS API this SDK was built/tested against, breaking face detection for
|
|
6
|
+
// every user at once with no code change on our side. Bump both together.
|
|
7
|
+
const MEDIAPIPE_VERSION = "0.10.32";
|
|
8
|
+
const WASM_CDN = `https://cdn.jsdelivr.net/npm/@mediapipe/tasks-vision@${MEDIAPIPE_VERSION}/wasm`;
|
|
9
|
+
// Also pinned (was "/latest/") so a model update can't shift blendshape
|
|
10
|
+
// output out from under ActionDetector's calibrated thresholds unannounced.
|
|
11
|
+
const MODEL_URL = "https://storage.googleapis.com/mediapipe-models/face_landmarker/face_landmarker/float16/1/face_landmarker.task";
|
|
4
12
|
// Module-level cache — survives component remounts and retries within the same page session.
|
|
5
13
|
// First init fetches ~8MB total (WASM + model); subsequent inits reuse the cache instantly.
|
|
6
|
-
|
|
7
|
-
|
|
14
|
+
// Cached as in-flight PROMISES (not resolved values) so concurrent init() calls
|
|
15
|
+
// (e.g. parallel calls from two liveness attempts, or a fast retry) share one
|
|
16
|
+
// fetch instead of racing duplicate downloads — and so a failed attempt
|
|
17
|
+
// (rejected promise) doesn't get treated as "cached" and reused forever.
|
|
18
|
+
let _visionPromise = null;
|
|
19
|
+
let _modelBufferPromise = null;
|
|
20
|
+
/** Max time to wait for the WASM runtime / model download before giving up. */
|
|
21
|
+
const INIT_TIMEOUT_MS = 20000;
|
|
22
|
+
function withTimeout(promise, ms, label) {
|
|
23
|
+
return new Promise((resolve, reject) => {
|
|
24
|
+
const timer = setTimeout(() => reject(new Error(`${label} timed out. Please check your connection and try again.`)), ms);
|
|
25
|
+
promise.then((value) => { clearTimeout(timer); resolve(value); }, (err) => { clearTimeout(timer); reject(err); });
|
|
26
|
+
});
|
|
27
|
+
}
|
|
8
28
|
export class FaceDetectorEngine {
|
|
9
29
|
constructor() {
|
|
10
30
|
this.landmarker = null;
|
|
11
31
|
}
|
|
12
32
|
async init() {
|
|
13
|
-
// Reuse WASM fileset — avoids re-fetching
|
|
14
|
-
|
|
15
|
-
|
|
33
|
+
// Reuse (or join) the in-flight WASM fileset load — avoids re-fetching
|
|
34
|
+
// ~3MB on retry/remount, and avoids kicking off a second parallel fetch
|
|
35
|
+
// if init() is called again before the first finishes.
|
|
36
|
+
if (!_visionPromise) {
|
|
37
|
+
_visionPromise = FilesetResolver.forVisionTasks(WASM_CDN);
|
|
38
|
+
_visionPromise.catch(() => { _visionPromise = null; }); // don't cache a failure
|
|
16
39
|
}
|
|
17
|
-
// Reuse
|
|
18
|
-
if (!
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
40
|
+
// Reuse (or join) the in-flight model download — same reasoning.
|
|
41
|
+
if (!_modelBufferPromise) {
|
|
42
|
+
_modelBufferPromise = fetch(MODEL_URL).then((res) => {
|
|
43
|
+
if (!res.ok)
|
|
44
|
+
throw new Error(`Failed to download face model (${res.status})`);
|
|
45
|
+
return res.arrayBuffer();
|
|
46
|
+
});
|
|
47
|
+
_modelBufferPromise.catch(() => { _modelBufferPromise = null; }); // don't cache a failure
|
|
24
48
|
}
|
|
25
|
-
|
|
49
|
+
const [vision, modelBuffer] = await withTimeout(Promise.all([_visionPromise, _modelBufferPromise]), INIT_TIMEOUT_MS, "Face detection setup");
|
|
50
|
+
this.landmarker = await withTimeout(FaceLandmarker.createFromOptions(vision, {
|
|
26
51
|
baseOptions: {
|
|
27
52
|
// Pass a copy — MediaPipe takes ownership of the buffer
|
|
28
|
-
modelAssetBuffer: new Uint8Array(
|
|
53
|
+
modelAssetBuffer: new Uint8Array(modelBuffer.slice(0)),
|
|
29
54
|
},
|
|
30
55
|
runningMode: "VIDEO",
|
|
31
56
|
outputFaceBlendshapes: true,
|
|
32
57
|
outputFacialTransformationMatrixes: true,
|
|
33
58
|
numFaces: 1,
|
|
34
|
-
});
|
|
59
|
+
}), INIT_TIMEOUT_MS, "Face detection setup");
|
|
35
60
|
}
|
|
36
61
|
detect(video, timestamp) {
|
|
37
62
|
if (!this.landmarker) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FaceDetector.js","sourceRoot":"","sources":["../../../src/camera/FaceDetector.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,eAAe,EACf,cAAc,GAEf,MAAM,yBAAyB,CAAC;AAEjC,MAAM,QAAQ,GACZ,
|
|
1
|
+
{"version":3,"file":"FaceDetector.js","sourceRoot":"","sources":["../../../src/camera/FaceDetector.ts"],"names":[],"mappings":"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"}
|
|
@@ -12,6 +12,16 @@ import { SessionResponse, SDKInitConfig } from "../types/onboarding";
|
|
|
12
12
|
* // ... use sdk.onboarding and sdk.liveness modules
|
|
13
13
|
*/
|
|
14
14
|
export declare class SmartComply {
|
|
15
|
+
/**
|
|
16
|
+
* Package version, hardcoded to match package.json — bump this alongside
|
|
17
|
+
* every version bump there (same manual-sync convention already used for
|
|
18
|
+
* MEDIAPIPE_VERSION in camera/FaceDetector.ts). Exists so a client's
|
|
19
|
+
* running version can be confirmed directly (SmartComply.VERSION, or the
|
|
20
|
+
* console log on construction below) instead of trusting that whatever
|
|
21
|
+
* CDN tag they installed with (e.g. @1, which floats to the latest
|
|
22
|
+
* matching release) actually resolved to the version they expect.
|
|
23
|
+
*/
|
|
24
|
+
static readonly VERSION = "1.0.79";
|
|
15
25
|
private http;
|
|
16
26
|
private clientId;
|
|
17
27
|
private _sessionToken;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Smartcomply.d.ts","sourceRoot":"","sources":["../../../src/client/Smartcomply.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAErC,OAAO,EAAE,gBAAgB,EAAE,MAAM,kCAAkC,CAAC;AACpE,OAAO,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;
|
|
1
|
+
{"version":3,"file":"Smartcomply.d.ts","sourceRoot":"","sources":["../../../src/client/Smartcomply.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAErC,OAAO,EAAE,gBAAgB,EAAE,MAAM,kCAAkC,CAAC;AACpE,OAAO,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAE9D,OAAO,EACL,eAAe,EACf,aAAa,EACd,MAAM,qBAAqB,CAAC;AAE7B;;;;;;;;GAQG;AACH,qBAAa,WAAW;IACtB;;;;;;;;OAQG;IACH,MAAM,CAAC,QAAQ,CAAC,OAAO,YAAY;IAEnC,OAAO,CAAC,IAAI,CAAa;IACzB,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,aAAa,CAAuB;IAC5C,OAAO,CAAC,iBAAiB,CAAuB;IAChD,OAAO,CAAC,UAAU,CAA8B;IAEzC,UAAU,EAAE,gBAAgB,CAAC;IAC7B,QAAQ,EAAE,cAAc,CAAC;gBAEpB,MAAM,EAAE,SAAS;IAiB7B,sDAAsD;IACtD,IAAI,YAAY,IAAI,MAAM,GAAG,IAAI,CAEhC;IAED,uCAAuC;IACvC,IAAI,gBAAgB,IAAI,MAAM,GAAG,IAAI,CAEpC;IAED,gFAAgF;IAChF,IAAI,SAAS,IAAI,aAAa,GAAG,IAAI,CAEpC;IAED;;;;;;;;OAQG;IACG,aAAa,IAAI,OAAO,CAAC,eAAe,CAAC;IAgB/C;;;;;;;;OAQG;IACG,gBAAgB,IAAI,OAAO,CAAC,aAAa,CAAC;CASjD"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { HttpClient } from "./HttpClient";
|
|
2
2
|
import { OnboardingModule } from "../modules/onboarding/onboarding";
|
|
3
3
|
import { LivenessModule } from "../modules/liveness/liveness";
|
|
4
|
+
import { SDKLogger } from "../utils/logger";
|
|
4
5
|
/**
|
|
5
6
|
* SmartComply SDK — main entry point.
|
|
6
7
|
*
|
|
@@ -25,6 +26,7 @@ export class SmartComply {
|
|
|
25
26
|
this.http = new HttpClient(config);
|
|
26
27
|
this.onboarding = new OnboardingModule(this.http);
|
|
27
28
|
this.liveness = new LivenessModule(this.http);
|
|
29
|
+
SDKLogger.always(`v${SmartComply.VERSION}`);
|
|
28
30
|
}
|
|
29
31
|
/** Current session token (null if not created yet) */
|
|
30
32
|
get sessionToken() {
|
|
@@ -70,4 +72,14 @@ export class SmartComply {
|
|
|
70
72
|
return config;
|
|
71
73
|
}
|
|
72
74
|
}
|
|
75
|
+
/**
|
|
76
|
+
* Package version, hardcoded to match package.json — bump this alongside
|
|
77
|
+
* every version bump there (same manual-sync convention already used for
|
|
78
|
+
* MEDIAPIPE_VERSION in camera/FaceDetector.ts). Exists so a client's
|
|
79
|
+
* running version can be confirmed directly (SmartComply.VERSION, or the
|
|
80
|
+
* console log on construction below) instead of trusting that whatever
|
|
81
|
+
* CDN tag they installed with (e.g. @1, which floats to the latest
|
|
82
|
+
* matching release) actually resolved to the version they expect.
|
|
83
|
+
*/
|
|
84
|
+
SmartComply.VERSION = "1.0.79";
|
|
73
85
|
//# sourceMappingURL=Smartcomply.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Smartcomply.js","sourceRoot":"","sources":["../../../src/client/Smartcomply.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,gBAAgB,EAAE,MAAM,kCAAkC,CAAC;AACpE,OAAO,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;
|
|
1
|
+
{"version":3,"file":"Smartcomply.js","sourceRoot":"","sources":["../../../src/client/Smartcomply.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,gBAAgB,EAAE,MAAM,kCAAkC,CAAC;AACpE,OAAO,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAC9D,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAM5C;;;;;;;;GAQG;AACH,MAAM,OAAO,WAAW;IAqBtB,YAAY,MAAiB;QAPrB,kBAAa,GAAkB,IAAI,CAAC;QACpC,sBAAiB,GAAkB,IAAI,CAAC;QACxC,eAAU,GAAyB,IAAI,CAAC;QAM9C,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC;YACnB,MAAM,IAAI,KAAK,CAAC,iCAAiC,CAAC,CAAC;QACrD,CAAC;QACD,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC;YACrB,MAAM,IAAI,KAAK,CAAC,+DAA+D,CAAC,CAAC;QACnF,CAAC;QAED,IAAI,CAAC,QAAQ,GAAG,MAAM,CAAC,QAAQ,CAAC;QAChC,IAAI,CAAC,IAAI,GAAG,IAAI,UAAU,CAAC,MAAM,CAAC,CAAC;QAEnC,IAAI,CAAC,UAAU,GAAG,IAAI,gBAAgB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAClD,IAAI,CAAC,QAAQ,GAAG,IAAI,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAE9C,SAAS,CAAC,MAAM,CAAC,IAAI,WAAW,CAAC,OAAO,EAAE,CAAC,CAAC;IAC9C,CAAC;IAED,sDAAsD;IACtD,IAAI,YAAY;QACd,OAAO,IAAI,CAAC,aAAa,CAAC;IAC5B,CAAC;IAED,uCAAuC;IACvC,IAAI,gBAAgB;QAClB,OAAO,IAAI,CAAC,iBAAiB,CAAC;IAChC,CAAC;IAED,gFAAgF;IAChF,IAAI,SAAS;QACX,OAAO,IAAI,CAAC,UAAU,CAAC;IACzB,CAAC;IAED;;;;;;;;OAQG;IACH,KAAK,CAAC,aAAa;QACjB,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,OAAO,CACtC,MAAM,EACN,qBAAqB,EACrB,EAAE,SAAS,EAAE,IAAI,CAAC,QAAQ,EAAE,CAC7B,CAAC;QAEF,IAAI,CAAC,aAAa,GAAG,QAAQ,CAAC,KAAK,CAAC;QACpC,IAAI,CAAC,iBAAiB,GAAG,QAAQ,CAAC,UAAU,CAAC;QAE7C,mEAAmE;QACnE,IAAI,CAAC,IAAI,CAAC,eAAe,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;QAE1C,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED;;;;;;;;OAQG;IACH,KAAK,CAAC,gBAAgB;QACpB,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,cAAc,CAC3C,KAAK,EACL,iBAAiB,CAClB,CAAC;QAEF,IAAI,CAAC,UAAU,GAAG,MAAM,CAAC;QACzB,OAAO,MAAM,CAAC;IAChB,CAAC;;AA9FD;;;;;;;;GAQG;AACa,mBAAO,GAAG,QAAQ,AAAX,CAAY"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SmartComplyFlow.d.ts","sourceRoot":"","sources":["../../../src/flow/SmartComplyFlow.ts"],"names":[],"mappings":"AACA,OAAO,EAA6B,sBAAsB,EAAE,MAAM,qBAAqB,CAAC;AAIxF,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"SmartComplyFlow.d.ts","sourceRoot":"","sources":["../../../src/flow/SmartComplyFlow.ts"],"names":[],"mappings":"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"}
|
|
@@ -18,6 +18,11 @@ const _INFRASTRUCTURE_ERROR_PATTERNS = [
|
|
|
18
18
|
"camera access is not supported",
|
|
19
19
|
"camera access failed",
|
|
20
20
|
"recording failed unexpectedly",
|
|
21
|
+
// FaceDetectorEngine.init() failures (FaceDetector.ts) — a slow/blocked
|
|
22
|
+
// CDN or model download is a connectivity issue, not a failed face scan,
|
|
23
|
+
// and must not burn one of the user's limited liveness retry attempts.
|
|
24
|
+
"face detection setup timed out",
|
|
25
|
+
"failed to download face model",
|
|
21
26
|
];
|
|
22
27
|
function _isInfrastructureError(err) {
|
|
23
28
|
const msg = String(err?.message || "").toLowerCase();
|
|
@@ -304,6 +309,11 @@ export class SmartComplyFlow {
|
|
|
304
309
|
this._keydownHandler = null;
|
|
305
310
|
this._visibilityHandler = null;
|
|
306
311
|
this._hiddenAtMs = null;
|
|
312
|
+
// Set just before a re-background restart re-renders the liveness step
|
|
313
|
+
// (see the visibilitychange handler below), read once by renderLiveness
|
|
314
|
+
// to show a "your scan was interrupted" notice instead of silently
|
|
315
|
+
// swapping back into a fresh scan with no explanation.
|
|
316
|
+
this._restartedAfterBackground = false;
|
|
307
317
|
this._popstateHandler = null;
|
|
308
318
|
this._historyGuardActive = false;
|
|
309
319
|
// Retry safety — max 3 confirmation rejections or liveness failures per session
|
|
@@ -547,6 +557,7 @@ export class SmartComplyFlow {
|
|
|
547
557
|
return;
|
|
548
558
|
const awayMs = Date.now() - hiddenAt;
|
|
549
559
|
if (awayMs >= REBACKGROUND_RESTART_MS && this.currentStep === "liveness") {
|
|
560
|
+
this._restartedAfterBackground = true;
|
|
550
561
|
this.showStep("liveness");
|
|
551
562
|
}
|
|
552
563
|
};
|
|
@@ -2034,6 +2045,10 @@ export class SmartComplyFlow {
|
|
|
2034
2045
|
// ── Liveness ────────────────────────────────────────────────────
|
|
2035
2046
|
renderLiveness(container) {
|
|
2036
2047
|
container.style.cssText += "display:flex;flex-direction:column;gap:14px;";
|
|
2048
|
+
// Consumed unconditionally (even on the retry-limit-reached exit below)
|
|
2049
|
+
// so it never leaks into a later, unrelated render of this step.
|
|
2050
|
+
const restartedAfterBackground = this._restartedAfterBackground;
|
|
2051
|
+
this._restartedAfterBackground = false;
|
|
2037
2052
|
// W13: Check retry limit before starting another liveness attempt
|
|
2038
2053
|
if (this._livenessFailures >= SmartComplyFlow.MAX_RETRIES) {
|
|
2039
2054
|
this._renderRetryLimitReached(container);
|
|
@@ -2044,6 +2059,18 @@ export class SmartComplyFlow {
|
|
|
2044
2059
|
// resolve/reject into the current one — see the visibilitychange
|
|
2045
2060
|
// handler in mount(), which re-renders this step on return-to-foreground.
|
|
2046
2061
|
const attemptId = ++this._livenessAttemptId;
|
|
2062
|
+
// Tell the user why the scan restarted instead of silently swapping
|
|
2063
|
+
// back into a fresh camera view with no explanation — a backgrounded
|
|
2064
|
+
// tab/app can leave the camera and detection loop in a stale state
|
|
2065
|
+
// (see the visibilitychange handler), so this restart is intentional,
|
|
2066
|
+
// but it must not look like the scan "just resumed" on its own.
|
|
2067
|
+
if (restartedAfterBackground) {
|
|
2068
|
+
const notice = document.createElement("div");
|
|
2069
|
+
notice.setAttribute("role", "status");
|
|
2070
|
+
notice.style.cssText = `width:100%;padding:10px 14px;border-radius:10px;background:${this.theme.warning}18;border:1px solid ${this.theme.warning}40;color:${this.theme.warning};font-size:12px;text-align:left;line-height:1.5;`;
|
|
2071
|
+
notice.textContent = "Your scan was interrupted when you left the page. Starting over — please stay on this screen until it's done.";
|
|
2072
|
+
container.appendChild(notice);
|
|
2073
|
+
}
|
|
2047
2074
|
const title = this.createStepTitle("Face verification");
|
|
2048
2075
|
container.appendChild(title);
|
|
2049
2076
|
const desc = document.createElement("div");
|