biometry-sdk 1.0.3 → 1.0.5
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/LICENSE +21 -0
- package/README.md +12 -0
- package/dist/index.js +2 -18
- package/dist/sdk.js +121 -215
- package/dist/sdk.test.js +243 -439
- package/dist/types.js +1 -2
- package/package.json +3 -2
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) [2024] [BIOMETRY]
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -28,3 +28,15 @@ const userFullName = "John Doe";
|
|
|
28
28
|
const response = await sdk.processVideo(videoFile, phrase, userFullName);
|
|
29
29
|
console.log(response);
|
|
30
30
|
```
|
|
31
|
+
|
|
32
|
+
## Example
|
|
33
|
+
|
|
34
|
+
You can find an example in the example/ directory. The example demonstrates how to integrate the SDK into a React app.
|
|
35
|
+
|
|
36
|
+
### License
|
|
37
|
+
|
|
38
|
+
This project is licensed under the MIT License. See the [LICENSE](LICENSE) file for more details.
|
|
39
|
+
|
|
40
|
+
### More Information
|
|
41
|
+
|
|
42
|
+
For more detailed documentation on the Biometry API, visit the [official documentation](https://developer.biometrysolutions.com/overview/).
|
package/dist/index.js
CHANGED
|
@@ -1,18 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
if (k2 === undefined) k2 = k;
|
|
4
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
-
}
|
|
8
|
-
Object.defineProperty(o, k2, desc);
|
|
9
|
-
}) : (function(o, m, k, k2) {
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
o[k2] = m[k];
|
|
12
|
-
}));
|
|
13
|
-
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
-
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
-
};
|
|
16
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
-
__exportStar(require("./sdk"), exports);
|
|
18
|
-
__exportStar(require("./types"), exports);
|
|
1
|
+
export * from './sdk';
|
|
2
|
+
export * from './types';
|
package/dist/sdk.js
CHANGED
|
@@ -1,92 +1,30 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
__assign = Object.assign || function(t) {
|
|
4
|
-
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
|
5
|
-
s = arguments[i];
|
|
6
|
-
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
|
|
7
|
-
t[p] = s[p];
|
|
8
|
-
}
|
|
9
|
-
return t;
|
|
10
|
-
};
|
|
11
|
-
return __assign.apply(this, arguments);
|
|
12
|
-
};
|
|
13
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
14
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
15
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
16
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
17
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
18
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
19
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
20
|
-
});
|
|
21
|
-
};
|
|
22
|
-
var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
23
|
-
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
|
|
24
|
-
return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
25
|
-
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
26
|
-
function step(op) {
|
|
27
|
-
if (f) throw new TypeError("Generator is already executing.");
|
|
28
|
-
while (g && (g = 0, op[0] && (_ = 0)), _) try {
|
|
29
|
-
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
|
30
|
-
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
31
|
-
switch (op[0]) {
|
|
32
|
-
case 0: case 1: t = op; break;
|
|
33
|
-
case 4: _.label++; return { value: op[1], done: false };
|
|
34
|
-
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
35
|
-
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
36
|
-
default:
|
|
37
|
-
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
38
|
-
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
39
|
-
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
40
|
-
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
41
|
-
if (t[2]) _.ops.pop();
|
|
42
|
-
_.trys.pop(); continue;
|
|
43
|
-
}
|
|
44
|
-
op = body.call(thisArg, _);
|
|
45
|
-
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
46
|
-
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
47
|
-
}
|
|
48
|
-
};
|
|
49
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
50
|
-
exports.BiometrySDK = void 0;
|
|
51
|
-
var BiometrySDK = /** @class */ (function () {
|
|
52
|
-
function BiometrySDK(apiKey) {
|
|
1
|
+
export class BiometrySDK {
|
|
2
|
+
constructor(apiKey) {
|
|
53
3
|
if (!apiKey) {
|
|
54
4
|
throw new Error('API Key is required to initialize the SDK.');
|
|
55
5
|
}
|
|
56
6
|
this.apiKey = apiKey;
|
|
57
7
|
}
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
}
|
|
72
|
-
return [4 /*yield*/, fetch("".concat(BiometrySDK.BASE_URL).concat(path), {
|
|
73
|
-
method: method,
|
|
74
|
-
headers: requestHeaders,
|
|
75
|
-
body: body,
|
|
76
|
-
})];
|
|
77
|
-
case 1:
|
|
78
|
-
response = _a.sent();
|
|
79
|
-
if (!!response.ok) return [3 /*break*/, 3];
|
|
80
|
-
return [4 /*yield*/, response.json()];
|
|
81
|
-
case 2:
|
|
82
|
-
error = _a.sent();
|
|
83
|
-
throw new Error("Error ".concat(response.status, ": ").concat(error.message));
|
|
84
|
-
case 3: return [4 /*yield*/, response.json()];
|
|
85
|
-
case 4: return [2 /*return*/, _a.sent()];
|
|
86
|
-
}
|
|
87
|
-
});
|
|
8
|
+
async request(path, method, body, headers) {
|
|
9
|
+
const defaultHeaders = {
|
|
10
|
+
Authorization: `Bearer ${this.apiKey}`,
|
|
11
|
+
};
|
|
12
|
+
const requestHeaders = Object.assign(Object.assign({}, defaultHeaders), headers);
|
|
13
|
+
if (body && !(body instanceof FormData)) {
|
|
14
|
+
requestHeaders['Content-Type'] = 'application/json';
|
|
15
|
+
body = JSON.stringify(body);
|
|
16
|
+
}
|
|
17
|
+
const response = await fetch(`${BiometrySDK.BASE_URL}${path}`, {
|
|
18
|
+
method,
|
|
19
|
+
headers: requestHeaders,
|
|
20
|
+
body,
|
|
88
21
|
});
|
|
89
|
-
|
|
22
|
+
if (!response.ok) {
|
|
23
|
+
const error = await response.json();
|
|
24
|
+
throw new Error(`Error ${response.status}: ${error.message}`);
|
|
25
|
+
}
|
|
26
|
+
return await response.json();
|
|
27
|
+
}
|
|
90
28
|
/**
|
|
91
29
|
* Submits consent for a user.
|
|
92
30
|
*
|
|
@@ -95,30 +33,20 @@ var BiometrySDK = /** @class */ (function () {
|
|
|
95
33
|
* @returns {Promise<ConsentResponse>} A promise resolving to the consent response.
|
|
96
34
|
* @throws {Error} - If the user's full name is not provided or if the request fails.
|
|
97
35
|
*/
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
case 1:
|
|
113
|
-
response = _a.sent();
|
|
114
|
-
return [2 /*return*/, {
|
|
115
|
-
is_consent_given: response.is_consent_given,
|
|
116
|
-
user_fullname: response.user_fullname,
|
|
117
|
-
}];
|
|
118
|
-
}
|
|
119
|
-
});
|
|
120
|
-
});
|
|
121
|
-
};
|
|
36
|
+
async giveConsent(isConsentGiven, userFullName) {
|
|
37
|
+
if (!userFullName) {
|
|
38
|
+
throw new Error('User Full Name is required to give consent.');
|
|
39
|
+
}
|
|
40
|
+
const body = {
|
|
41
|
+
is_consent_given: isConsentGiven,
|
|
42
|
+
user_fullname: userFullName,
|
|
43
|
+
};
|
|
44
|
+
const response = await this.request('/consent', 'POST', body);
|
|
45
|
+
return {
|
|
46
|
+
is_consent_given: response.is_consent_given,
|
|
47
|
+
user_fullname: response.user_fullname,
|
|
48
|
+
};
|
|
49
|
+
}
|
|
122
50
|
/**
|
|
123
51
|
* Onboards a user's voice for biometric authentication.
|
|
124
52
|
*
|
|
@@ -130,32 +58,27 @@ var BiometrySDK = /** @class */ (function () {
|
|
|
130
58
|
* @returns {Promise<VoiceOnboardingResponse>} - A promise resolving to the voice onboarding response.
|
|
131
59
|
* @throws {Error} - If required parameters are missing or the request fails.
|
|
132
60
|
*/
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
}
|
|
155
|
-
return [2 /*return*/, this.request('/api-gateway/onboard/voice', 'POST', formData, headers)];
|
|
156
|
-
});
|
|
157
|
-
});
|
|
158
|
-
};
|
|
61
|
+
async onboardVoice(audio, userFullName, uniqueId, phrase, requestUserProvidedId) {
|
|
62
|
+
if (!userFullName)
|
|
63
|
+
throw new Error('User fullname is required.');
|
|
64
|
+
if (!uniqueId)
|
|
65
|
+
throw new Error('Unique ID is required.');
|
|
66
|
+
if (!phrase)
|
|
67
|
+
throw new Error('Phrase is required.');
|
|
68
|
+
if (!audio)
|
|
69
|
+
throw new Error('Audio file is required.');
|
|
70
|
+
const formData = new FormData();
|
|
71
|
+
formData.append('unique_id', uniqueId);
|
|
72
|
+
formData.append('phrase', phrase);
|
|
73
|
+
formData.append('voice', audio);
|
|
74
|
+
const headers = {
|
|
75
|
+
'X-User-Fullname': userFullName,
|
|
76
|
+
};
|
|
77
|
+
if (requestUserProvidedId) {
|
|
78
|
+
headers['X-Request-User-Provided-ID'] = requestUserProvidedId;
|
|
79
|
+
}
|
|
80
|
+
return this.request('/api-gateway/onboard/voice', 'POST', formData, headers);
|
|
81
|
+
}
|
|
159
82
|
/**
|
|
160
83
|
* Onboards a user's face for biometric authentication.
|
|
161
84
|
*
|
|
@@ -166,29 +89,24 @@ var BiometrySDK = /** @class */ (function () {
|
|
|
166
89
|
* @returns {Promise<FaceOnboardingResponse>} - A promise resolving to the voice onboarding response.
|
|
167
90
|
* @throws {Error} - If required parameters are missing or the request fails.
|
|
168
91
|
*/
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
}
|
|
188
|
-
return [2 /*return*/, this.request('/api-gateway/onboard/face', 'POST', formData, headers)];
|
|
189
|
-
});
|
|
190
|
-
});
|
|
191
|
-
};
|
|
92
|
+
async onboardFace(face, userFullName, isDocument, requestUserProvidedId) {
|
|
93
|
+
if (!userFullName)
|
|
94
|
+
throw new Error('User fullname is required.');
|
|
95
|
+
if (!face)
|
|
96
|
+
throw new Error('Face image is required.');
|
|
97
|
+
const formData = new FormData();
|
|
98
|
+
formData.append('face', face);
|
|
99
|
+
if (isDocument) {
|
|
100
|
+
formData.append('is_document', 'true');
|
|
101
|
+
}
|
|
102
|
+
const headers = {
|
|
103
|
+
'X-User-Fullname': userFullName,
|
|
104
|
+
};
|
|
105
|
+
if (requestUserProvidedId) {
|
|
106
|
+
headers['X-Request-User-Provided-ID'] = requestUserProvidedId;
|
|
107
|
+
}
|
|
108
|
+
return this.request('/api-gateway/onboard/face', 'POST', formData, headers);
|
|
109
|
+
}
|
|
192
110
|
/**
|
|
193
111
|
* Matches a user's face from video against a reference image.
|
|
194
112
|
*
|
|
@@ -201,36 +119,31 @@ var BiometrySDK = /** @class */ (function () {
|
|
|
201
119
|
* @returns {Promise<FaceMatchResponse>} - A promise resolving to the voice onboarding response.
|
|
202
120
|
* @throws {Error} - If required parameters are missing or the request fails.
|
|
203
121
|
*/
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
}
|
|
230
|
-
return [2 /*return*/, this.request('/api-gateway/match-faces', 'POST', formData, headers)];
|
|
231
|
-
});
|
|
232
|
-
});
|
|
233
|
-
};
|
|
122
|
+
async matchFaces(image, video, userFullName, processVideoRequestId, usePrefilledVideo, requestUserProvidedId) {
|
|
123
|
+
if (!image)
|
|
124
|
+
throw new Error('Face image is required.');
|
|
125
|
+
if ((!processVideoRequestId && !usePrefilledVideo) && !video)
|
|
126
|
+
throw new Error('Video is required.');
|
|
127
|
+
const formData = new FormData();
|
|
128
|
+
if (video) {
|
|
129
|
+
formData.append('video', video);
|
|
130
|
+
}
|
|
131
|
+
formData.append('image', image);
|
|
132
|
+
const headers = {};
|
|
133
|
+
if (userFullName) {
|
|
134
|
+
headers['X-User-Fullname'] = userFullName;
|
|
135
|
+
}
|
|
136
|
+
if (processVideoRequestId) {
|
|
137
|
+
headers['X-Request-Id'] = processVideoRequestId;
|
|
138
|
+
}
|
|
139
|
+
if (processVideoRequestId && usePrefilledVideo) {
|
|
140
|
+
headers['X-Use-Prefilled-Video'] = 'true';
|
|
141
|
+
}
|
|
142
|
+
if (requestUserProvidedId) {
|
|
143
|
+
headers['X-Request-User-Provided-ID'] = requestUserProvidedId;
|
|
144
|
+
}
|
|
145
|
+
return this.request('/api-gateway/match-faces', 'POST', formData, headers);
|
|
146
|
+
}
|
|
234
147
|
/**
|
|
235
148
|
* Process the video through Biometry services to check liveness and authorize user
|
|
236
149
|
*
|
|
@@ -241,32 +154,25 @@ var BiometrySDK = /** @class */ (function () {
|
|
|
241
154
|
* @param {object} deviceInfo - Pass the device information in JSON format to include in transaction.
|
|
242
155
|
* @returns
|
|
243
156
|
*/
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
});
|
|
267
|
-
});
|
|
268
|
-
};
|
|
269
|
-
BiometrySDK.BASE_URL = 'https://api.biometrysolutions.com';
|
|
270
|
-
return BiometrySDK;
|
|
271
|
-
}());
|
|
272
|
-
exports.BiometrySDK = BiometrySDK;
|
|
157
|
+
async processVideo(video, phrase, userFullName, requestUserProvidedId, deviceInfo) {
|
|
158
|
+
if (!video)
|
|
159
|
+
throw new Error('Video is required.');
|
|
160
|
+
if (!phrase)
|
|
161
|
+
throw new Error('Phrase is required.');
|
|
162
|
+
const formData = new FormData();
|
|
163
|
+
formData.append('phrase', phrase);
|
|
164
|
+
formData.append('video', video);
|
|
165
|
+
const headers = {};
|
|
166
|
+
if (userFullName) {
|
|
167
|
+
headers['X-User-Fullname'] = userFullName;
|
|
168
|
+
}
|
|
169
|
+
if (requestUserProvidedId) {
|
|
170
|
+
headers['X-Request-User-Provided-ID'] = requestUserProvidedId;
|
|
171
|
+
}
|
|
172
|
+
if (deviceInfo) {
|
|
173
|
+
headers['X-Device-Info'] = JSON.stringify(deviceInfo);
|
|
174
|
+
}
|
|
175
|
+
return this.request('/api-gateway/process-video', 'POST', formData, headers);
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
BiometrySDK.BASE_URL = 'https://api.biometrysolutions.com';
|
package/dist/sdk.test.js
CHANGED
|
@@ -1,451 +1,255 @@
|
|
|
1
|
-
|
|
2
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
-
});
|
|
10
|
-
};
|
|
11
|
-
var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
12
|
-
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
|
|
13
|
-
return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
14
|
-
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
15
|
-
function step(op) {
|
|
16
|
-
if (f) throw new TypeError("Generator is already executing.");
|
|
17
|
-
while (g && (g = 0, op[0] && (_ = 0)), _) try {
|
|
18
|
-
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
|
19
|
-
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
20
|
-
switch (op[0]) {
|
|
21
|
-
case 0: case 1: t = op; break;
|
|
22
|
-
case 4: _.label++; return { value: op[1], done: false };
|
|
23
|
-
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
24
|
-
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
25
|
-
default:
|
|
26
|
-
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
27
|
-
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
28
|
-
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
29
|
-
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
30
|
-
if (t[2]) _.ops.pop();
|
|
31
|
-
_.trys.pop(); continue;
|
|
32
|
-
}
|
|
33
|
-
op = body.call(thisArg, _);
|
|
34
|
-
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
35
|
-
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
36
|
-
}
|
|
37
|
-
};
|
|
38
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
-
var sdk_1 = require("./sdk");
|
|
1
|
+
import { BiometrySDK } from './sdk';
|
|
40
2
|
// Mock the fetch API globally
|
|
41
3
|
global.fetch = jest.fn();
|
|
42
|
-
describe('BiometrySDK',
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
afterEach(
|
|
4
|
+
describe('BiometrySDK', () => {
|
|
5
|
+
const apiKey = 'test-api-key';
|
|
6
|
+
const sdk = new BiometrySDK(apiKey);
|
|
7
|
+
afterEach(() => {
|
|
46
8
|
jest.clearAllMocks();
|
|
47
9
|
});
|
|
48
|
-
it('should throw an error if no API key is provided',
|
|
49
|
-
expect(
|
|
10
|
+
it('should throw an error if no API key is provided', () => {
|
|
11
|
+
expect(() => new BiometrySDK('')).toThrow('API Key is required to initialize the SDK.');
|
|
50
12
|
});
|
|
51
13
|
// CONSENT
|
|
52
|
-
it('should call fetch with correct headers and body when giving consent',
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
}));
|
|
77
|
-
expect(result).toEqual({ is_consent_given: true, user_fullname: 'John Doe', });
|
|
78
|
-
return [2 /*return*/];
|
|
79
|
-
}
|
|
80
|
-
});
|
|
81
|
-
}); });
|
|
82
|
-
it('should throw an error if response is not ok', function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
83
|
-
return __generator(this, function (_a) {
|
|
84
|
-
switch (_a.label) {
|
|
85
|
-
case 0:
|
|
86
|
-
fetch.mockResolvedValueOnce({
|
|
87
|
-
ok: false,
|
|
88
|
-
status: 400,
|
|
89
|
-
json: function () { return __awaiter(void 0, void 0, void 0, function () { return __generator(this, function (_a) {
|
|
90
|
-
return [2 /*return*/, ({ error: 'is_consent_given must be true' })];
|
|
91
|
-
}); }); },
|
|
92
|
-
});
|
|
93
|
-
return [4 /*yield*/, expect(sdk.giveConsent(true, 'John Doe')).rejects.toThrow('Error 400: undefined')];
|
|
94
|
-
case 1:
|
|
95
|
-
_a.sent();
|
|
96
|
-
return [2 /*return*/];
|
|
97
|
-
}
|
|
14
|
+
it('should call fetch with correct headers and body when giving consent', async () => {
|
|
15
|
+
fetch.mockResolvedValueOnce({
|
|
16
|
+
ok: true,
|
|
17
|
+
json: async () => ({ is_consent_given: true, user_fullname: 'John Doe' }),
|
|
18
|
+
});
|
|
19
|
+
const result = await sdk.giveConsent(true, 'John Doe');
|
|
20
|
+
expect(fetch).toHaveBeenCalledWith('https://api.biometrysolutions.com/consent', expect.objectContaining({
|
|
21
|
+
method: 'POST',
|
|
22
|
+
headers: {
|
|
23
|
+
Authorization: `Bearer ${apiKey}`,
|
|
24
|
+
'Content-Type': 'application/json',
|
|
25
|
+
},
|
|
26
|
+
body: JSON.stringify({
|
|
27
|
+
is_consent_given: true,
|
|
28
|
+
user_fullname: 'John Doe',
|
|
29
|
+
}),
|
|
30
|
+
}));
|
|
31
|
+
expect(result).toEqual({ is_consent_given: true, user_fullname: 'John Doe', });
|
|
32
|
+
});
|
|
33
|
+
it('should throw an error if response is not ok', async () => {
|
|
34
|
+
fetch.mockResolvedValueOnce({
|
|
35
|
+
ok: false,
|
|
36
|
+
status: 400,
|
|
37
|
+
json: async () => ({ error: 'is_consent_given must be true' }),
|
|
98
38
|
});
|
|
99
|
-
|
|
39
|
+
await expect(sdk.giveConsent(true, 'John Doe')).rejects.toThrow('Error 400: undefined');
|
|
40
|
+
});
|
|
100
41
|
// VOICE ONBOARDING
|
|
101
|
-
it('should throw an error if user fullname is missing',
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
case 0: return [4 /*yield*/, expect(sdk.onboardVoice(null, 'User Name', 'uniqueId', 'phrase')).rejects.toThrowError('Audio file is required.')];
|
|
144
|
-
case 1:
|
|
145
|
-
_a.sent();
|
|
146
|
-
return [2 /*return*/];
|
|
147
|
-
}
|
|
148
|
-
});
|
|
149
|
-
}); });
|
|
150
|
-
it('should successfully onboard voice and return the response', function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
151
|
-
var mockResponse, audioFile, userFullName, uniqueId, phrase, formDataSpy, result;
|
|
152
|
-
return __generator(this, function (_a) {
|
|
153
|
-
switch (_a.label) {
|
|
154
|
-
case 0:
|
|
155
|
-
mockResponse = {
|
|
156
|
-
status: 'good',
|
|
157
|
-
};
|
|
158
|
-
fetch.mockResolvedValueOnce({
|
|
159
|
-
ok: true,
|
|
160
|
-
json: function () { return __awaiter(void 0, void 0, void 0, function () { return __generator(this, function (_a) {
|
|
161
|
-
return [2 /*return*/, mockResponse];
|
|
162
|
-
}); }); },
|
|
163
|
-
});
|
|
164
|
-
audioFile = new File(['audio data'], 'audio.wav', { type: 'audio/wav' });
|
|
165
|
-
userFullName = 'User Name';
|
|
166
|
-
uniqueId = 'uniqueId';
|
|
167
|
-
phrase = 'phrase';
|
|
168
|
-
formDataSpy = jest.spyOn(FormData.prototype, 'append');
|
|
169
|
-
return [4 /*yield*/, sdk.onboardVoice(audioFile, userFullName, uniqueId, phrase)];
|
|
170
|
-
case 1:
|
|
171
|
-
result = _a.sent();
|
|
172
|
-
expect(formDataSpy).toHaveBeenCalledWith('unique_id', uniqueId);
|
|
173
|
-
expect(formDataSpy).toHaveBeenCalledWith('phrase', phrase);
|
|
174
|
-
expect(formDataSpy).toHaveBeenCalledWith('voice', audioFile);
|
|
175
|
-
expect(fetch).toHaveBeenCalledWith('https://api.biometrysolutions.com/api-gateway/onboard/voice', expect.objectContaining({
|
|
176
|
-
method: 'POST',
|
|
177
|
-
headers: {
|
|
178
|
-
'Authorization': "Bearer ".concat(apiKey),
|
|
179
|
-
'X-User-Fullname': userFullName,
|
|
180
|
-
},
|
|
181
|
-
body: expect.any(FormData)
|
|
182
|
-
}));
|
|
183
|
-
expect(result).toEqual(mockResponse);
|
|
184
|
-
return [2 /*return*/];
|
|
185
|
-
}
|
|
186
|
-
});
|
|
187
|
-
}); });
|
|
42
|
+
it('should throw an error if user fullname is missing', async () => {
|
|
43
|
+
const audioFile = new File(['audio data'], 'audio.wav', { type: 'audio/wav' });
|
|
44
|
+
await expect(sdk.onboardVoice(audioFile, '', 'uniqueId', 'phrase')).rejects.toThrowError('User fullname is required.');
|
|
45
|
+
});
|
|
46
|
+
it('should throw an error if unique ID is missing', async () => {
|
|
47
|
+
const audioFile = new File(['audio data'], 'audio.wav', { type: 'audio/wav' });
|
|
48
|
+
await expect(sdk.onboardVoice(audioFile, 'User Name', '', 'phrase')).rejects.toThrowError('Unique ID is required.');
|
|
49
|
+
});
|
|
50
|
+
it('should throw an error if phrase is missing', async () => {
|
|
51
|
+
const audioFile = new File(['audio data'], 'audio.wav', { type: 'audio/wav' });
|
|
52
|
+
await expect(sdk.onboardVoice(audioFile, 'User Name', 'uniqueId', '')).rejects.toThrowError('Phrase is required.');
|
|
53
|
+
});
|
|
54
|
+
it('should throw an error if audio file is missing', async () => {
|
|
55
|
+
await expect(sdk.onboardVoice(null, 'User Name', 'uniqueId', 'phrase')).rejects.toThrowError('Audio file is required.');
|
|
56
|
+
});
|
|
57
|
+
it('should successfully onboard voice and return the response', async () => {
|
|
58
|
+
const mockResponse = {
|
|
59
|
+
status: 'good',
|
|
60
|
+
};
|
|
61
|
+
fetch.mockResolvedValueOnce({
|
|
62
|
+
ok: true,
|
|
63
|
+
json: async () => mockResponse,
|
|
64
|
+
});
|
|
65
|
+
const audioFile = new File(['audio data'], 'audio.wav', { type: 'audio/wav' });
|
|
66
|
+
const userFullName = 'User Name';
|
|
67
|
+
const uniqueId = 'uniqueId';
|
|
68
|
+
const phrase = 'phrase';
|
|
69
|
+
const formDataSpy = jest.spyOn(FormData.prototype, 'append');
|
|
70
|
+
const result = await sdk.onboardVoice(audioFile, userFullName, uniqueId, phrase);
|
|
71
|
+
expect(formDataSpy).toHaveBeenCalledWith('unique_id', uniqueId);
|
|
72
|
+
expect(formDataSpy).toHaveBeenCalledWith('phrase', phrase);
|
|
73
|
+
expect(formDataSpy).toHaveBeenCalledWith('voice', audioFile);
|
|
74
|
+
expect(fetch).toHaveBeenCalledWith('https://api.biometrysolutions.com/api-gateway/onboard/voice', expect.objectContaining({
|
|
75
|
+
method: 'POST',
|
|
76
|
+
headers: {
|
|
77
|
+
'Authorization': `Bearer ${apiKey}`,
|
|
78
|
+
'X-User-Fullname': userFullName,
|
|
79
|
+
},
|
|
80
|
+
body: expect.any(FormData)
|
|
81
|
+
}));
|
|
82
|
+
expect(result).toEqual(mockResponse);
|
|
83
|
+
});
|
|
188
84
|
// FACE ONBOARDING
|
|
189
|
-
it('should throw an error if user fullname is missing',
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
};
|
|
221
|
-
fetch.mockResolvedValueOnce({
|
|
222
|
-
ok: true,
|
|
223
|
-
json: function () { return __awaiter(void 0, void 0, void 0, function () { return __generator(this, function (_a) {
|
|
224
|
-
return [2 /*return*/, mockResponse];
|
|
225
|
-
}); }); },
|
|
226
|
-
});
|
|
227
|
-
imageFile = new File(['image data'], 'image.jpg', { type: 'image/jpeg' });
|
|
228
|
-
userFullName = 'User Name';
|
|
229
|
-
formDataSpy = jest.spyOn(FormData.prototype, 'append');
|
|
230
|
-
return [4 /*yield*/, sdk.onboardFace(imageFile, userFullName)];
|
|
231
|
-
case 1:
|
|
232
|
-
result = _a.sent();
|
|
233
|
-
expect(formDataSpy).toHaveBeenCalledWith('face', imageFile);
|
|
234
|
-
expect(fetch).toHaveBeenCalledWith('https://api.biometrysolutions.com/api-gateway/onboard/face', expect.objectContaining({
|
|
235
|
-
method: 'POST',
|
|
236
|
-
headers: {
|
|
237
|
-
'Authorization': "Bearer ".concat(apiKey),
|
|
238
|
-
'X-User-Fullname': userFullName,
|
|
239
|
-
},
|
|
240
|
-
body: expect.any(FormData)
|
|
241
|
-
}));
|
|
242
|
-
expect(result).toEqual(mockResponse);
|
|
243
|
-
return [2 /*return*/];
|
|
244
|
-
}
|
|
245
|
-
});
|
|
246
|
-
}); });
|
|
85
|
+
it('should throw an error if user fullname is missing', async () => {
|
|
86
|
+
const imageFile = new File(['image data'], 'image.jpg', { type: 'image/jpeg' });
|
|
87
|
+
await expect(sdk.onboardFace(imageFile, '')).rejects.toThrowError('User fullname is required.');
|
|
88
|
+
});
|
|
89
|
+
it('should throw an error if image file is missing', async () => {
|
|
90
|
+
await expect(sdk.onboardFace(null, 'User Name')).rejects.toThrowError('Face image is required.');
|
|
91
|
+
});
|
|
92
|
+
it('should successfully onboard face and return the response', async () => {
|
|
93
|
+
const mockResponse = {
|
|
94
|
+
code: 200,
|
|
95
|
+
description: 'Face onboarded successfully',
|
|
96
|
+
};
|
|
97
|
+
fetch.mockResolvedValueOnce({
|
|
98
|
+
ok: true,
|
|
99
|
+
json: async () => mockResponse,
|
|
100
|
+
});
|
|
101
|
+
const imageFile = new File(['image data'], 'image.jpg', { type: 'image/jpeg' });
|
|
102
|
+
const userFullName = 'User Name';
|
|
103
|
+
const formDataSpy = jest.spyOn(FormData.prototype, 'append');
|
|
104
|
+
const result = await sdk.onboardFace(imageFile, userFullName);
|
|
105
|
+
expect(formDataSpy).toHaveBeenCalledWith('face', imageFile);
|
|
106
|
+
expect(fetch).toHaveBeenCalledWith('https://api.biometrysolutions.com/api-gateway/onboard/face', expect.objectContaining({
|
|
107
|
+
method: 'POST',
|
|
108
|
+
headers: {
|
|
109
|
+
'Authorization': `Bearer ${apiKey}`,
|
|
110
|
+
'X-User-Fullname': userFullName,
|
|
111
|
+
},
|
|
112
|
+
body: expect.any(FormData)
|
|
113
|
+
}));
|
|
114
|
+
expect(result).toEqual(mockResponse);
|
|
115
|
+
});
|
|
247
116
|
// FACE MATCH
|
|
248
|
-
it('should throw an error if face image is missing',
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
result: 1,
|
|
323
|
-
description: 'Matched',
|
|
324
|
-
anchor: {
|
|
325
|
-
code: 200,
|
|
326
|
-
description: 'Anchor face',
|
|
327
|
-
},
|
|
328
|
-
target: {
|
|
329
|
-
code: 200,
|
|
330
|
-
description: 'Target face',
|
|
331
|
-
},
|
|
332
|
-
};
|
|
333
|
-
fetch.mockResolvedValueOnce({
|
|
334
|
-
ok: true,
|
|
335
|
-
json: function () { return __awaiter(void 0, void 0, void 0, function () { return __generator(this, function (_a) {
|
|
336
|
-
return [2 /*return*/, mockResponse];
|
|
337
|
-
}); }); },
|
|
338
|
-
});
|
|
339
|
-
imageFile = new File(['image data'], 'image.jpg', { type: 'image/jpeg' });
|
|
340
|
-
formDataSpy = jest.spyOn(FormData.prototype, 'append');
|
|
341
|
-
return [4 /*yield*/, sdk.matchFaces(imageFile, undefined, 'User Name', 'processVideoRequestId', true)];
|
|
342
|
-
case 1:
|
|
343
|
-
result = _a.sent();
|
|
344
|
-
expect(formDataSpy).toHaveBeenCalledWith('image', imageFile);
|
|
345
|
-
expect(fetch).toHaveBeenCalledWith('https://api.biometrysolutions.com/api-gateway/match-faces', expect.objectContaining({
|
|
346
|
-
method: 'POST',
|
|
347
|
-
headers: {
|
|
348
|
-
'Authorization': "Bearer ".concat(apiKey),
|
|
349
|
-
'X-User-Fullname': 'User Name',
|
|
350
|
-
'X-Request-Id': 'processVideoRequestId',
|
|
351
|
-
'X-Use-Prefilled-Video': 'true',
|
|
352
|
-
},
|
|
353
|
-
body: expect.any(FormData)
|
|
354
|
-
}));
|
|
355
|
-
expect(result).toEqual(mockResponse);
|
|
356
|
-
return [2 /*return*/];
|
|
357
|
-
}
|
|
358
|
-
});
|
|
359
|
-
}); });
|
|
117
|
+
it('should throw an error if face image is missing', async () => {
|
|
118
|
+
await expect(sdk.matchFaces(null, null)).rejects.toThrowError('Face image is required.');
|
|
119
|
+
});
|
|
120
|
+
it('should throw an error if video file is missing', async () => {
|
|
121
|
+
const imageFile = new File(['image data'], 'image.jpg', { type: 'image/jpeg' });
|
|
122
|
+
await expect(sdk.matchFaces(imageFile, null)).rejects.toThrowError('Video is required.');
|
|
123
|
+
});
|
|
124
|
+
it('should successfully match faces and return the response', async () => {
|
|
125
|
+
const mockResponse = {
|
|
126
|
+
code: 200,
|
|
127
|
+
result: 1,
|
|
128
|
+
description: 'Matched',
|
|
129
|
+
anchor: {
|
|
130
|
+
code: 200,
|
|
131
|
+
description: 'Anchor face',
|
|
132
|
+
},
|
|
133
|
+
target: {
|
|
134
|
+
code: 200,
|
|
135
|
+
description: 'Target face',
|
|
136
|
+
},
|
|
137
|
+
};
|
|
138
|
+
fetch.mockResolvedValueOnce({
|
|
139
|
+
ok: true,
|
|
140
|
+
json: async () => mockResponse,
|
|
141
|
+
});
|
|
142
|
+
const imageFile = new File(['image data'], 'image.jpg', { type: 'image/jpeg' });
|
|
143
|
+
const videoFile = new File(['video data'], 'video.mp4', { type: 'video/mp4' });
|
|
144
|
+
const formDataSpy = jest.spyOn(FormData.prototype, 'append');
|
|
145
|
+
const result = await sdk.matchFaces(imageFile, videoFile);
|
|
146
|
+
expect(formDataSpy).toHaveBeenCalledWith('video', videoFile);
|
|
147
|
+
expect(formDataSpy).toHaveBeenCalledWith('image', imageFile);
|
|
148
|
+
expect(fetch).toHaveBeenCalledWith('https://api.biometrysolutions.com/api-gateway/match-faces', expect.objectContaining({
|
|
149
|
+
method: 'POST',
|
|
150
|
+
headers: {
|
|
151
|
+
'Authorization': `Bearer ${apiKey}`,
|
|
152
|
+
},
|
|
153
|
+
body: expect.any(FormData)
|
|
154
|
+
}));
|
|
155
|
+
expect(result).toEqual(mockResponse);
|
|
156
|
+
});
|
|
157
|
+
it('should successfully match faces if processVideoRequestId is provided', async () => {
|
|
158
|
+
const mockResponse = {
|
|
159
|
+
code: 200,
|
|
160
|
+
result: 1,
|
|
161
|
+
description: 'Matched',
|
|
162
|
+
anchor: {
|
|
163
|
+
code: 200,
|
|
164
|
+
description: 'Anchor face',
|
|
165
|
+
},
|
|
166
|
+
target: {
|
|
167
|
+
code: 200,
|
|
168
|
+
description: 'Target face',
|
|
169
|
+
},
|
|
170
|
+
};
|
|
171
|
+
fetch.mockResolvedValueOnce({
|
|
172
|
+
ok: true,
|
|
173
|
+
json: async () => mockResponse,
|
|
174
|
+
});
|
|
175
|
+
const imageFile = new File(['image data'], 'image.jpg', { type: 'image/jpeg' });
|
|
176
|
+
const formDataSpy = jest.spyOn(FormData.prototype, 'append');
|
|
177
|
+
const result = await sdk.matchFaces(imageFile, undefined, 'User Name', 'processVideoRequestId', true);
|
|
178
|
+
expect(formDataSpy).toHaveBeenCalledWith('image', imageFile);
|
|
179
|
+
expect(fetch).toHaveBeenCalledWith('https://api.biometrysolutions.com/api-gateway/match-faces', expect.objectContaining({
|
|
180
|
+
method: 'POST',
|
|
181
|
+
headers: {
|
|
182
|
+
'Authorization': `Bearer ${apiKey}`,
|
|
183
|
+
'X-User-Fullname': 'User Name',
|
|
184
|
+
'X-Request-Id': 'processVideoRequestId',
|
|
185
|
+
'X-Use-Prefilled-Video': 'true',
|
|
186
|
+
},
|
|
187
|
+
body: expect.any(FormData)
|
|
188
|
+
}));
|
|
189
|
+
expect(result).toEqual(mockResponse);
|
|
190
|
+
});
|
|
360
191
|
// PROCESS VIDEO
|
|
361
|
-
it('should throw an error if video file is missing',
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
};
|
|
425
|
-
fetch.mockResolvedValueOnce({
|
|
426
|
-
ok: true,
|
|
427
|
-
json: function () { return __awaiter(void 0, void 0, void 0, function () { return __generator(this, function (_a) {
|
|
428
|
-
return [2 /*return*/, mockResponse];
|
|
429
|
-
}); }); },
|
|
430
|
-
});
|
|
431
|
-
videoFile = new File(['video data'], 'video.mp4', { type: 'video/mp4' });
|
|
432
|
-
phrase = 'ONE TWO THREE FOUR FIVE SIX SEVEN EIGHT';
|
|
433
|
-
formDataSpy = jest.spyOn(FormData.prototype, 'append');
|
|
434
|
-
return [4 /*yield*/, sdk.processVideo(videoFile, phrase)];
|
|
435
|
-
case 1:
|
|
436
|
-
result = _a.sent();
|
|
437
|
-
expect(formDataSpy).toHaveBeenCalledWith('video', videoFile);
|
|
438
|
-
expect(formDataSpy).toHaveBeenCalledWith('phrase', phrase);
|
|
439
|
-
expect(fetch).toHaveBeenCalledWith('https://api.biometrysolutions.com/api-gateway/process-video', expect.objectContaining({
|
|
440
|
-
method: 'POST',
|
|
441
|
-
headers: {
|
|
442
|
-
'Authorization': "Bearer ".concat(apiKey),
|
|
443
|
-
},
|
|
444
|
-
body: expect.any(FormData)
|
|
445
|
-
}));
|
|
446
|
-
expect(result).toEqual(mockResponse);
|
|
447
|
-
return [2 /*return*/];
|
|
448
|
-
}
|
|
449
|
-
});
|
|
450
|
-
}); });
|
|
192
|
+
it('should throw an error if video file is missing', async () => {
|
|
193
|
+
await expect(sdk.processVideo(null, 'phrase')).rejects.toThrowError('Video is required.');
|
|
194
|
+
});
|
|
195
|
+
it('should throw an error if phrase is missing', async () => {
|
|
196
|
+
const videoFile = new File(['video data'], 'video.mp4', { type: 'video/mp4' });
|
|
197
|
+
await expect(sdk.processVideo(videoFile, '')).rejects.toThrowError('Phrase is required.');
|
|
198
|
+
});
|
|
199
|
+
it('should successfully process video and return the response', async () => {
|
|
200
|
+
const mockResponse = {
|
|
201
|
+
data: {
|
|
202
|
+
'Active Speaker Detection': {
|
|
203
|
+
code: 0,
|
|
204
|
+
description: 'Successful check',
|
|
205
|
+
result: 90.00,
|
|
206
|
+
},
|
|
207
|
+
'Face Liveness Detection': {
|
|
208
|
+
code: 0,
|
|
209
|
+
description: 'Successful check',
|
|
210
|
+
result: true,
|
|
211
|
+
},
|
|
212
|
+
'Face Recognition': {
|
|
213
|
+
code: 0,
|
|
214
|
+
description: 'Successful check',
|
|
215
|
+
},
|
|
216
|
+
'Visual Speech Recognition': {
|
|
217
|
+
code: 0,
|
|
218
|
+
description: 'Successful check',
|
|
219
|
+
result: 'ONE TWO THREE FOUR FIVE SIX SEVEN EIGHT',
|
|
220
|
+
},
|
|
221
|
+
'Voice Recognition': {
|
|
222
|
+
status: 'good',
|
|
223
|
+
id: '123',
|
|
224
|
+
score: 0.99,
|
|
225
|
+
imposter_prob: 0.01,
|
|
226
|
+
log_odds: '1.0',
|
|
227
|
+
},
|
|
228
|
+
},
|
|
229
|
+
result_conditions: {
|
|
230
|
+
failed_conditions: [],
|
|
231
|
+
failed_refer_conditions: [],
|
|
232
|
+
status: 'pass',
|
|
233
|
+
},
|
|
234
|
+
message: 'video processed successfully',
|
|
235
|
+
};
|
|
236
|
+
fetch.mockResolvedValueOnce({
|
|
237
|
+
ok: true,
|
|
238
|
+
json: async () => mockResponse,
|
|
239
|
+
});
|
|
240
|
+
const videoFile = new File(['video data'], 'video.mp4', { type: 'video/mp4' });
|
|
241
|
+
const phrase = 'ONE TWO THREE FOUR FIVE SIX SEVEN EIGHT';
|
|
242
|
+
const formDataSpy = jest.spyOn(FormData.prototype, 'append');
|
|
243
|
+
const result = await sdk.processVideo(videoFile, phrase);
|
|
244
|
+
expect(formDataSpy).toHaveBeenCalledWith('video', videoFile);
|
|
245
|
+
expect(formDataSpy).toHaveBeenCalledWith('phrase', phrase);
|
|
246
|
+
expect(fetch).toHaveBeenCalledWith('https://api.biometrysolutions.com/api-gateway/process-video', expect.objectContaining({
|
|
247
|
+
method: 'POST',
|
|
248
|
+
headers: {
|
|
249
|
+
'Authorization': `Bearer ${apiKey}`,
|
|
250
|
+
},
|
|
251
|
+
body: expect.any(FormData)
|
|
252
|
+
}));
|
|
253
|
+
expect(result).toEqual(mockResponse);
|
|
254
|
+
});
|
|
451
255
|
});
|
package/dist/types.js
CHANGED
|
@@ -1,2 +1 @@
|
|
|
1
|
-
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
1
|
+
export {};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "biometry-sdk",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.5",
|
|
4
4
|
"main": "dist/index.js",
|
|
5
5
|
"types": "dist/index.d.ts",
|
|
6
6
|
"files": [
|
|
@@ -12,5 +12,6 @@
|
|
|
12
12
|
},
|
|
13
13
|
"devDependencies": {
|
|
14
14
|
"typescript": "^5.0.0"
|
|
15
|
-
}
|
|
15
|
+
},
|
|
16
|
+
"license": "MIT"
|
|
16
17
|
}
|