verant_id_cloud_scan 1.4.2 → 1.4.4-beta.0

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.
@@ -0,0 +1,9 @@
1
+ {
2
+ "permissions": {
3
+ "allow": [
4
+ "Bash(git add:*)"
5
+ ],
6
+ "deny": [],
7
+ "ask": []
8
+ }
9
+ }
@@ -0,0 +1,27 @@
1
+ # .github/workflows/publish.yml
2
+ name: Publish to npm
3
+ on:
4
+ push:
5
+ tags:
6
+ - "v*.*.*"
7
+ jobs:
8
+ publish:
9
+ runs-on: ubuntu-latest
10
+ permissions:
11
+ contents: read
12
+ id-token: write
13
+ steps:
14
+ - name: Checkout repo
15
+ uses: actions/checkout@v4
16
+
17
+ - name: Use Node
18
+ uses: actions/setup-node@v4
19
+ with:
20
+ node-version: "22"
21
+ registry-url: "https://registry.npmjs.org"
22
+
23
+ - name: Update npm
24
+ run: npm install -g npm@latest
25
+
26
+ - name: Publish to npm
27
+ run: npm publish
package/Api.js CHANGED
@@ -1,5 +1,3 @@
1
- import { compressAndCompareImages } from "./FaceComparison.js";
2
-
3
1
  //prod
4
2
  const licenseServerAddress = "https://lic.verantid.com/api/v1";
5
3
  const dmvServerAddress = "https://dmv.verantid.com/api/v1/dmv_check";
@@ -7,7 +5,7 @@ const dmvServerAddress = "https://dmv.verantid.com/api/v1/dmv_check";
7
5
  // const licenseServerAddress =
8
6
  // "https://verant-license-server-staging-52b03b060a98.herokuapp.com/api/v1";
9
7
  // const dmvServerAddress =
10
- // "https://dmv-check-server-staging-fcaab48bec21.herokuapp.com/api/v1/dmv_check"; // Replace with staging or production URL
8
+ // "https://dmv-check-server-staging-fcaab48bec21.herokuapp.com/api/v1/dmv_check";
11
9
 
12
10
  // Helper function that checks multiple possible keys and returns a non-empty value
13
11
  const getLicenseFieldValue = (data, possibleKeys) => {
@@ -286,7 +284,13 @@ const postToScannerApi = async (
286
284
  commandObj,
287
285
  timeout = 10000
288
286
  ) => {
289
- let apiAddress =`${scannerAddress}/securelink`;
287
+ // Ensure the scanner address has a protocol (http:// or https://)
288
+ let formattedAddress = scannerAddress;
289
+ if (!scannerAddress.startsWith('http://') && !scannerAddress.startsWith('https://')) {
290
+ formattedAddress = `http://${scannerAddress}`;
291
+ }
292
+
293
+ let apiAddress = `${formattedAddress}/securelink`;
290
294
 
291
295
  const controller = new AbortController();
292
296
  const signal = controller.signal;
@@ -337,4 +341,42 @@ export const stopScanning = (scannerAddress, commandObj) =>
337
341
  postToScannerApi(scannerAddress, commandObj);
338
342
 
339
343
  export const closeConnection = (scannerAddress, commandObj) =>
340
- postToScannerApi(scannerAddress, commandObj);
344
+ postToScannerApi(scannerAddress, commandObj);
345
+
346
+ // Check if scanner is present by attempting to connect and disconnect
347
+ export const checkScannerPresent = async (scannerAddress) => {
348
+ try {
349
+ // Generate a unique message ID for this check
350
+ const messageId = new Date().toISOString();
351
+
352
+ // Attempt to establish connection
353
+ const connectCommand = {
354
+ Command: "Connect",
355
+ MessageId: messageId,
356
+ Exclusive: "false", // Use non-exclusive mode for just checking
357
+ IdleTimeout: "5",
358
+ };
359
+
360
+ const connectResponse = await postToScannerApi(scannerAddress, connectCommand, 5000);
361
+
362
+ // If connection failed or no session ID, scanner not present
363
+ if (!connectResponse || !connectResponse.SessionId) {
364
+ return false;
365
+ }
366
+
367
+ // Got a session ID, now disconnect
368
+ const disconnectCommand = {
369
+ Command: "Disconnect",
370
+ MessageId: new Date().toISOString(),
371
+ SessionId: connectResponse.SessionId,
372
+ };
373
+
374
+ await postToScannerApi(scannerAddress, disconnectCommand, 5000);
375
+
376
+ // Successfully connected and disconnected
377
+ return true;
378
+ } catch (error) {
379
+ // Any error means scanner is not reachable
380
+ return false;
381
+ }
382
+ };
package/CloudScan.js CHANGED
@@ -4,7 +4,7 @@ import {
4
4
  readBarcode,
5
5
  } from "./BarcodeScanner.js";
6
6
  import { driverLicenseFields } from "./DriverLicenseFields.js";
7
- import { localScannerChain, scanBack } from "./LocalScannerApi.js";
7
+ import { localScannerChain, scanBack, scanFrontOnly } from "./LocalScannerApi.js";
8
8
  import { compressAndCompareImages, compressImage } from "./FaceComparison.js";
9
9
  import {
10
10
  checkDmvFeatureLicense,
@@ -12,6 +12,7 @@ import {
12
12
  dmvCheck,
13
13
  getBarcodeLicenseKey,
14
14
  scannerChain,
15
+ scannerPresent,
15
16
  } from "./ScannerApi.js";
16
17
 
17
18
  let cachedLicenseFrontBase64 = "";
@@ -32,6 +33,8 @@ export const checkFaceCompareFeature = async (clientId) => {
32
33
  return await checkFaceComparisonFeatureLicense(clientId);
33
34
  }
34
35
 
36
+ export { scannerPresent };
37
+
35
38
  export async function readImageBarcode(imageFile) {
36
39
  let returnObj = {
37
40
  barcodeResultsObject: {},
@@ -204,7 +207,7 @@ export const localScanId = async (scannerAddress, clientId) => {
204
207
  return true;
205
208
  };
206
209
 
207
- export const localContinueScanId = async (scannerAddress, includeData) => {
210
+ export const localContinueScanId = async (scannerAddress, includeData, skipBackScan = false) => {
208
211
  let barcodeResultsObject = {};
209
212
  let returnObj = {
210
213
  barcodeResultsObject,
@@ -217,9 +220,16 @@ export const localContinueScanId = async (scannerAddress, includeData) => {
217
220
  scannerAddress = "https://localhost:53051";
218
221
  }
219
222
 
220
- let scannerResponseObj = await scanBack(scannerAddress, includeData);
223
+ let scannerResponseObj;
221
224
 
222
- //console.log(scannerResponseObj);
225
+ if (skipBackScan) {
226
+ // For facial verification only, skip back scan
227
+ scannerResponseObj = await scanFrontOnly();
228
+ }
229
+ else {
230
+ scannerResponseObj = await scanBack(scannerAddress, includeData);
231
+ }
232
+
223
233
  if (scannerResponseObj.errorMessages.length > 0) {
224
234
  returnObj.errorMessages = scannerResponseObj.errorMessages;
225
235
  return returnObj;
package/FaceComparison.js CHANGED
@@ -1,3 +1,9 @@
1
+ //prod
2
+ // const faceComparisonAddress = "https://faceid.verantid.com/compare_id_and_face";
3
+ //staging
4
+ const faceComparisonAddress = "https://staging.face.verantid.bluerocket.us/compare_id_and_face";
5
+
6
+
1
7
  export async function compressImage(source, maxSize = 2 * 1024 * 1024) {
2
8
  async function _shrink(canvas) {
3
9
  let quality = 0.95;
@@ -36,7 +42,7 @@ export async function compressImage(source, maxSize = 2 * 1024 * 1024) {
36
42
  }
37
43
 
38
44
  const startComparison = async (commandObj) => {
39
- return fetch("https://staging.face.verantid.bluerocket.us/compare_id_and_face", {
45
+ return fetch(faceComparisonAddress, {
40
46
  method: "POST",
41
47
  headers: { "Content-Type": "application/json" },
42
48
  body: JSON.stringify(commandObj)
@@ -69,14 +75,29 @@ export async function compressAndCompareImages(
69
75
 
70
76
  const res = await startComparison(imagesObject);
71
77
  const data = await res.json();
78
+
72
79
  const confidence = data?.SourceImageFace?.Confidence?.toFixed(2);
73
80
  const similarity = data?.FaceMatches?.[0]?.Similarity?.toFixed(2) || 0;
74
81
 
75
- let range = "Not the same";
82
+ let range = "No match";
76
83
  if (similarity >= 80) range = "Likely match";
77
84
  else if (similarity >= 60) range = "Likely not the same";
78
85
 
79
- return { similarity, confidence, range };
86
+ const result = {
87
+ similarity,
88
+ confidence,
89
+ range,
90
+ };
91
+
92
+ // Only include error if present
93
+ if (data?.error || data?.details) {
94
+ result.error = {
95
+ error: data?.error,
96
+ details: data?.details,
97
+ };
98
+ }
99
+
100
+ return result;
80
101
  }
81
102
 
82
103
  async function base64ToCanvas(src) {
@@ -189,6 +189,18 @@ export async function localScannerChain(ambirApiAddress, clientId) {
189
189
  };
190
190
  }
191
191
 
192
+ export async function scanFrontOnly() {
193
+ // Skip the back scan entirely, close the connection
194
+ await closeScannerConnection();
195
+ return {
196
+ success: true,
197
+ scanDataResults,
198
+ licenseFrontBase64: licenseFrontBase64,
199
+ licenseBackBase64: "",
200
+ errorMessages,
201
+ };
202
+ }
203
+
192
204
  export async function scanBack() {
193
205
  //6a set the back params for this session
194
206
  const setParamsSuccess = await setScanParameters(false);
package/ScannerApi.js CHANGED
@@ -41,6 +41,10 @@ export async function dmvCheck(clientId, scannerType, licenseData) {
41
41
  return await API.dmvCheck(clientId, scannerType, licenseData);
42
42
  }
43
43
 
44
+ export async function scannerPresent(scannerAddress) {
45
+ return await API.checkScannerPresent(scannerAddress);
46
+ }
47
+
44
48
  //This is the top level function that calls the other functions in order
45
49
  export async function scannerChain(
46
50
  scannerAddress,
package/index.d.ts CHANGED
@@ -45,7 +45,8 @@ declare module "verant_id_cloud_scan" {
45
45
 
46
46
  export function localContinueScanId(
47
47
  scannerAddress: string,
48
- includeData: boolean
48
+ includeData: boolean,
49
+ skipBackScan?: boolean
49
50
  ): Promise<{
50
51
  barcodeResultsObject: any;
51
52
  licenseFrontBase64: string;
@@ -53,3 +54,5 @@ declare module "verant_id_cloud_scan" {
53
54
  errorMessages: string;
54
55
  }>;
55
56
  }
57
+
58
+ export function scannerPresent(scannerAddress: string): Promise<boolean>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "verant_id_cloud_scan",
3
- "version": "1.4.2",
3
+ "version": "1.4.4-beta.0",
4
4
  "description": "Verant ID Cloud Scan NPM Library",
5
5
  "main": "CloudScan.js",
6
6
  "types": "index.d.ts",