scandoc-ai-components 0.0.99 → 0.1.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 +4 -6
- package/dist/index.js +114 -36
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -42,8 +42,7 @@ An example HTML page integration:
|
|
|
42
42
|
|
|
43
43
|
<script src="scandoc.js"></script>
|
|
44
44
|
<script>
|
|
45
|
-
const
|
|
46
|
-
createScanDocAIConfig(key, "test");
|
|
45
|
+
const token = ""
|
|
47
46
|
|
|
48
47
|
setScanDocAIConfig({
|
|
49
48
|
SHOULD_RETURN_DOCUMENT_IMAGE: true,
|
|
@@ -54,7 +53,7 @@ An example HTML page integration:
|
|
|
54
53
|
MAX_UNSUPPORTED_ATTEMPTS: 5,
|
|
55
54
|
});
|
|
56
55
|
|
|
57
|
-
const extractionVideo = getExtractionVideo(function (result) {
|
|
56
|
+
const extractionVideo = getExtractionVideo(token, function (result) {
|
|
58
57
|
console.log("Extraction Result:", result);
|
|
59
58
|
if (result.success) {
|
|
60
59
|
extractionVideo.reset();
|
|
@@ -82,8 +81,7 @@ An example React integration:
|
|
|
82
81
|
import { useEffect, useMemo } from "react";
|
|
83
82
|
import "scandoc-ai-components/dist/index"
|
|
84
83
|
|
|
85
|
-
const
|
|
86
|
-
window.createScanDocAIConfig(key, "test");
|
|
84
|
+
const token = "";
|
|
87
85
|
window.setScanDocAIConfig({
|
|
88
86
|
SHOULD_RETURN_DOCUMENT_IMAGE: true,
|
|
89
87
|
SHOULD_RETURN_FACE_IF_DETECTED: true,
|
|
@@ -93,7 +91,7 @@ window.setScanDocAIConfig({
|
|
|
93
91
|
MAX_UNSUPPORTED_ATTEMPTS: 4,
|
|
94
92
|
});
|
|
95
93
|
|
|
96
|
-
const extractionVideo = window.getExtractionVideo(result => {
|
|
94
|
+
const extractionVideo = window.getExtractionVideo(token, result => {
|
|
97
95
|
console.log("Extraction Result:", result);
|
|
98
96
|
if (result.success) {
|
|
99
97
|
extractionVideo.reset();
|
package/dist/index.js
CHANGED
|
@@ -11180,8 +11180,7 @@ class ExtractorVideo {
|
|
|
11180
11180
|
},
|
|
11181
11181
|
height: {
|
|
11182
11182
|
ideal: 1080
|
|
11183
|
-
}
|
|
11184
|
-
facingMode: "environment"
|
|
11183
|
+
}
|
|
11185
11184
|
});
|
|
11186
11185
|
constructor(onExtractedResults) {
|
|
11187
11186
|
this.candidateImages = [];
|
|
@@ -11350,7 +11349,7 @@ class ExtractorVideo {
|
|
|
11350
11349
|
async startVideo() {
|
|
11351
11350
|
try {
|
|
11352
11351
|
const serviceConfig = (0,_config__WEBPACK_IMPORTED_MODULE_1__.getScanDocAIConfig)();
|
|
11353
|
-
await serviceConfig.getAccessToken(
|
|
11352
|
+
await serviceConfig.getAccessToken(false);
|
|
11354
11353
|
const videoElem = document.getElementById("ScanDocAIVideoElement");
|
|
11355
11354
|
if (!videoElem) {
|
|
11356
11355
|
throw new Error("Video element not found.");
|
|
@@ -11358,22 +11357,47 @@ class ExtractorVideo {
|
|
|
11358
11357
|
this.video = videoElem;
|
|
11359
11358
|
this.isRunning = true;
|
|
11360
11359
|
this.scanStartTime = Date.now();
|
|
11360
|
+
const cfgValues = (0,_config__WEBPACK_IMPORTED_MODULE_1__.getScanDocAIConfigValues)();
|
|
11361
|
+
const mode = cfgValues.VIDEO_FACING_MODE ?? "environment";
|
|
11361
11362
|
const devices = await navigator.mediaDevices.enumerateDevices();
|
|
11362
11363
|
const environmentCameras = devices.filter(device => device.kind === "videoinput" && device.label.toLowerCase().includes("back"));
|
|
11363
|
-
const cameras = await checkAutofocusSupport(environmentCameras);
|
|
11364
11364
|
let deviceId;
|
|
11365
|
-
if (
|
|
11366
|
-
|
|
11365
|
+
if (mode === "environment") {
|
|
11366
|
+
const af = await checkAutofocusSupport(environmentCameras);
|
|
11367
|
+
deviceId = af[0]?.deviceId || environmentCameras[0]?.deviceId;
|
|
11367
11368
|
}
|
|
11368
|
-
const
|
|
11369
|
-
|
|
11369
|
+
const buildConstraints = () => {
|
|
11370
|
+
const base = {
|
|
11371
|
+
...ExtractorVideo.VIDEO_SETTINGS
|
|
11372
|
+
};
|
|
11373
|
+
if (typeof mode === "string") {
|
|
11374
|
+
base.facingMode = {
|
|
11375
|
+
ideal: mode
|
|
11376
|
+
}; // "environment" | "user"
|
|
11377
|
+
} else if (mode && typeof mode === "object") {
|
|
11378
|
+
base.facingMode = mode; // e.g. { exact: "user" }
|
|
11379
|
+
} else {
|
|
11380
|
+
base.facingMode = {
|
|
11381
|
+
ideal: "environment"
|
|
11382
|
+
};
|
|
11383
|
+
}
|
|
11384
|
+
if (mode === "environment" && deviceId) {
|
|
11385
|
+
base.deviceId = {
|
|
11386
|
+
exact: deviceId
|
|
11387
|
+
};
|
|
11388
|
+
}
|
|
11389
|
+
return {
|
|
11390
|
+
video: base
|
|
11391
|
+
};
|
|
11370
11392
|
};
|
|
11371
|
-
|
|
11372
|
-
|
|
11393
|
+
let stream;
|
|
11394
|
+
try {
|
|
11395
|
+
stream = await navigator.mediaDevices.getUserMedia(buildConstraints());
|
|
11396
|
+
} catch (e) {
|
|
11397
|
+
stream = await navigator.mediaDevices.getUserMedia({
|
|
11398
|
+
video: true
|
|
11399
|
+
});
|
|
11373
11400
|
}
|
|
11374
|
-
const stream = await navigator.mediaDevices.getUserMedia({
|
|
11375
|
-
video: userMediaConstraints
|
|
11376
|
-
});
|
|
11377
11401
|
this.video.srcObject = stream;
|
|
11378
11402
|
await this.video.play().catch(e => {
|
|
11379
11403
|
console.warn(`Error on video play: ${e}`);
|
|
@@ -11394,7 +11418,7 @@ class ExtractorVideo {
|
|
|
11394
11418
|
this.onExtractedResults({
|
|
11395
11419
|
success: false,
|
|
11396
11420
|
code: error.status === 401 || error.status === 403 ? "004" : "005",
|
|
11397
|
-
info: error.status === 401 || error.status === 403 ? "Authentication failed: Invalid API key." : "Startup failed: " + (error.message || "Unknown error")
|
|
11421
|
+
info: error.status === 401 || error.status === 403 ? "Authentication failed: Invalid API key/token." : "Startup failed: " + (error.message || "Unknown error")
|
|
11398
11422
|
});
|
|
11399
11423
|
return false;
|
|
11400
11424
|
}
|
|
@@ -11438,8 +11462,7 @@ class ExtractorVideo {
|
|
|
11438
11462
|
const cfgValues = (0,_config__WEBPACK_IMPORTED_MODULE_1__.getScanDocAIConfigValues)();
|
|
11439
11463
|
const borderColor = cfgValues.VIDEO_COLORS?.borderColor;
|
|
11440
11464
|
const messageColor = cfgValues.VIDEO_COLORS?.messageColor;
|
|
11441
|
-
const isMobile = window.innerWidth < 768 || window.innerHeight > window.innerWidth;
|
|
11442
|
-
window.innerWidth < 768 || window.innerHeight > window.innerWidth && window.innerWidth < 1024;
|
|
11465
|
+
const isMobile = window.innerWidth < 768 || window.innerHeight > window.innerWidth && window.innerWidth < 1024;
|
|
11443
11466
|
if (isMobile) {
|
|
11444
11467
|
// Mobile version with overlay feedback
|
|
11445
11468
|
return `
|
|
@@ -11508,7 +11531,7 @@ class ExtractorVideo {
|
|
|
11508
11531
|
<div class="desktopFeedback" id="ScanDocAIMessage"></div>
|
|
11509
11532
|
<div class="desktopVideoArea">
|
|
11510
11533
|
<div class="desktopVideoHolder">
|
|
11511
|
-
<video id="ScanDocAIVideoElement" class="desktopVideo"
|
|
11534
|
+
<video id="ScanDocAIVideoElement" class="desktopVideo" autoplay muted playsinline></video>
|
|
11512
11535
|
<div class="backgroundOverlay"></div>
|
|
11513
11536
|
<div class="centerGuideDot"></div>
|
|
11514
11537
|
</div>
|
|
@@ -11587,11 +11610,29 @@ class ExtractorVideo {
|
|
|
11587
11610
|
}
|
|
11588
11611
|
}
|
|
11589
11612
|
let EXTRACTION_VIDEO = undefined;
|
|
11590
|
-
function getExtractionVideo(
|
|
11591
|
-
|
|
11592
|
-
|
|
11613
|
+
function getExtractionVideo(tokenOrCallback, maybeCallback) {
|
|
11614
|
+
let token;
|
|
11615
|
+
let cb;
|
|
11616
|
+
if (typeof tokenOrCallback === "function") {
|
|
11617
|
+
cb = tokenOrCallback;
|
|
11593
11618
|
} else {
|
|
11594
|
-
|
|
11619
|
+
token = tokenOrCallback;
|
|
11620
|
+
cb = maybeCallback;
|
|
11621
|
+
}
|
|
11622
|
+
if (token !== undefined) {
|
|
11623
|
+
(0,_config__WEBPACK_IMPORTED_MODULE_1__.setScanDocAIAccessToken)(token);
|
|
11624
|
+
}
|
|
11625
|
+
if (EXTRACTION_VIDEO === undefined) {
|
|
11626
|
+
if (typeof cb !== "function") {
|
|
11627
|
+
throw new Error("getExtractionVideo requires a callback.");
|
|
11628
|
+
}
|
|
11629
|
+
EXTRACTION_VIDEO = new ExtractorVideo(cb);
|
|
11630
|
+
return EXTRACTION_VIDEO;
|
|
11631
|
+
}
|
|
11632
|
+
|
|
11633
|
+
// If called again, update callback too
|
|
11634
|
+
if (typeof cb === "function") {
|
|
11635
|
+
EXTRACTION_VIDEO.onExtractedResults = cb;
|
|
11595
11636
|
}
|
|
11596
11637
|
return EXTRACTION_VIDEO;
|
|
11597
11638
|
}
|
|
@@ -11611,12 +11652,14 @@ async function checkAutofocusSupport(environmentCameras) {
|
|
|
11611
11652
|
// Try to access camera stream with autofocus enabled
|
|
11612
11653
|
const stream = await navigator.mediaDevices.getUserMedia(constraints);
|
|
11613
11654
|
const tracks = stream.getVideoTracks();
|
|
11614
|
-
|
|
11615
|
-
|
|
11616
|
-
|
|
11617
|
-
|
|
11618
|
-
|
|
11619
|
-
|
|
11655
|
+
const track = tracks[0];
|
|
11656
|
+
if (track) {
|
|
11657
|
+
// Check if autofocus is supported
|
|
11658
|
+
const capabilities = track.getCapabilities();
|
|
11659
|
+
// console.log(capabilities);
|
|
11660
|
+
if (capabilities.focusMode && capabilities.focusMode.includes("continuous")) {
|
|
11661
|
+
camerasWithAutofocus.push(camera);
|
|
11662
|
+
}
|
|
11620
11663
|
}
|
|
11621
11664
|
|
|
11622
11665
|
// Cleanup
|
|
@@ -11680,6 +11723,7 @@ __webpack_require__.r(__webpack_exports__);
|
|
|
11680
11723
|
/* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__),
|
|
11681
11724
|
/* harmony export */ getScanDocAIConfig: () => (/* binding */ getScanDocAIConfig),
|
|
11682
11725
|
/* harmony export */ getScanDocAIConfigValues: () => (/* binding */ getScanDocAIConfigValues),
|
|
11726
|
+
/* harmony export */ setScanDocAIAccessToken: () => (/* binding */ setScanDocAIAccessToken),
|
|
11683
11727
|
/* harmony export */ setScanDocAIConfig: () => (/* binding */ setScanDocAIConfig)
|
|
11684
11728
|
/* harmony export */ });
|
|
11685
11729
|
let internalConfig = {
|
|
@@ -11694,6 +11738,7 @@ let internalConfig = {
|
|
|
11694
11738
|
MAX_REQUEST_TRY: 3,
|
|
11695
11739
|
MAX_AUTH_TRY: 3,
|
|
11696
11740
|
USE_KEY_SERVICE: true,
|
|
11741
|
+
VIDEO_FACING_MODE: "environment",
|
|
11697
11742
|
// validation settings:
|
|
11698
11743
|
VALIDATION_CONTRAST_BORDER_SIZE: null,
|
|
11699
11744
|
VALIDATION_CONTRAST_THRESHOLD: null,
|
|
@@ -11732,9 +11777,9 @@ function setScanDocAIConfig(newConfig = {}) {
|
|
|
11732
11777
|
internalConfig = {
|
|
11733
11778
|
...internalConfig,
|
|
11734
11779
|
...newConfig,
|
|
11735
|
-
|
|
11736
|
-
...internalConfig.
|
|
11737
|
-
...newConfig.
|
|
11780
|
+
VIDEO_COLORS: {
|
|
11781
|
+
...internalConfig.VIDEO_COLORS,
|
|
11782
|
+
...newConfig.VIDEO_COLORS
|
|
11738
11783
|
}
|
|
11739
11784
|
};
|
|
11740
11785
|
}
|
|
@@ -11831,6 +11876,34 @@ class InactiveServiceConfig {
|
|
|
11831
11876
|
}
|
|
11832
11877
|
async refreshTokens() {}
|
|
11833
11878
|
}
|
|
11879
|
+
class TokenServiceConfig {
|
|
11880
|
+
static CONFIG = undefined;
|
|
11881
|
+
constructor() {
|
|
11882
|
+
this.accessToken = undefined;
|
|
11883
|
+
}
|
|
11884
|
+
setAccessToken(token) {
|
|
11885
|
+
this.accessToken = token || undefined;
|
|
11886
|
+
}
|
|
11887
|
+
async getAccessToken() {
|
|
11888
|
+
if (!this.accessToken) {
|
|
11889
|
+
const err = new Error("Missing access token");
|
|
11890
|
+
err.status = 401;
|
|
11891
|
+
throw err;
|
|
11892
|
+
}
|
|
11893
|
+
return this.accessToken;
|
|
11894
|
+
}
|
|
11895
|
+
async refreshTokens() {
|
|
11896
|
+
// client provides a new token
|
|
11897
|
+
}
|
|
11898
|
+
}
|
|
11899
|
+
function setScanDocAIAccessToken(token) {
|
|
11900
|
+
const config = getScanDocAIConfigValues();
|
|
11901
|
+
if (config.USE_KEY_SERVICE === false) return;
|
|
11902
|
+
if (TokenServiceConfig.CONFIG === undefined) {
|
|
11903
|
+
TokenServiceConfig.CONFIG = new TokenServiceConfig();
|
|
11904
|
+
}
|
|
11905
|
+
TokenServiceConfig.CONFIG.setAccessToken(token);
|
|
11906
|
+
}
|
|
11834
11907
|
function createScanDocAIConfig(staticKey, subClient) {
|
|
11835
11908
|
const config = getScanDocAIConfigValues();
|
|
11836
11909
|
if (config.USE_KEY_SERVICE) {
|
|
@@ -11846,11 +11919,15 @@ function getScanDocAIConfig() {
|
|
|
11846
11919
|
if (config.USE_KEY_SERVICE === false) {
|
|
11847
11920
|
return new InactiveServiceConfig();
|
|
11848
11921
|
}
|
|
11849
|
-
|
|
11850
|
-
|
|
11851
|
-
throw new Error("Service config not created!");
|
|
11922
|
+
if (TokenServiceConfig.CONFIG !== undefined) {
|
|
11923
|
+
return TokenServiceConfig.CONFIG;
|
|
11852
11924
|
}
|
|
11853
|
-
|
|
11925
|
+
if (ServiceConfig.CONFIG !== undefined) {
|
|
11926
|
+
return ServiceConfig.CONFIG;
|
|
11927
|
+
}
|
|
11928
|
+
const err = new Error("Service config not created (missing token or static key)!");
|
|
11929
|
+
err.status = 401;
|
|
11930
|
+
throw err;
|
|
11854
11931
|
}
|
|
11855
11932
|
/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (createScanDocAIConfig);
|
|
11856
11933
|
|
|
@@ -11960,7 +12037,7 @@ async function callDocumentExtraction(frontImage, backImage, ignoreBackImage) {
|
|
|
11960
12037
|
const response = await fetch(`${cfgValues.SCAN_APP_URL}extraction/`, {
|
|
11961
12038
|
method: "POST",
|
|
11962
12039
|
headers: {
|
|
11963
|
-
Authorization: await serviceConfig.getAccessToken(
|
|
12040
|
+
Authorization: await serviceConfig.getAccessToken(false),
|
|
11964
12041
|
Accept: "application/json",
|
|
11965
12042
|
"Content-Type": "application/json"
|
|
11966
12043
|
},
|
|
@@ -11987,6 +12064,7 @@ async function callDocumentExtraction(frontImage, backImage, ignoreBackImage) {
|
|
|
11987
12064
|
}
|
|
11988
12065
|
//
|
|
11989
12066
|
if (response.status === 401 || response.status === 403) {
|
|
12067
|
+
errors = ["Token expired/invalid"];
|
|
11990
12068
|
await serviceConfig.refreshTokens();
|
|
11991
12069
|
} else {
|
|
11992
12070
|
const data = await response.json();
|
|
@@ -12070,7 +12148,7 @@ async function callDocumentValidation(images, blur_values) {
|
|
|
12070
12148
|
}
|
|
12071
12149
|
//
|
|
12072
12150
|
if (response.status === 401 || response.status === 403) {
|
|
12073
|
-
errors = ["
|
|
12151
|
+
errors = ["Token expired/invalid"];
|
|
12074
12152
|
await serviceConfig.refreshTokens();
|
|
12075
12153
|
} else {
|
|
12076
12154
|
const data = await response.json();
|