facecog-liveness-showcase 0.0.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.
Files changed (229) hide show
  1. package/.browserslistrc +15 -0
  2. package/.dockerignore +48 -0
  3. package/.editorconfig +16 -0
  4. package/.eslintrc.json +47 -0
  5. package/.vercelignore +7 -0
  6. package/.vscode/extensions.json +5 -0
  7. package/.vscode/settings.json +3 -0
  8. package/DOCKER.md +221 -0
  9. package/Dockerfile +33 -0
  10. package/README.md +268 -0
  11. package/angular.json +156 -0
  12. package/capacitor.config.ts +9 -0
  13. package/docker-compose.dev.yml +20 -0
  14. package/docker-compose.yml +18 -0
  15. package/ionic.config.json +7 -0
  16. package/jest.config.js +38 -0
  17. package/nginx.conf +50 -0
  18. package/package.json +131 -0
  19. package/patches/ng-packagr+20.3.2.patch +60 -0
  20. package/projects/facecog-liveness-verification/README.md +295 -0
  21. package/projects/facecog-liveness-verification/ng-package.json +7 -0
  22. package/projects/facecog-liveness-verification/package.json +48 -0
  23. package/projects/facecog-liveness-verification/scripts/build-with-wrapper-copy.js +38 -0
  24. package/projects/facecog-liveness-verification/scripts/copy-wrapper-after-ngc.js +35 -0
  25. package/projects/facecog-liveness-verification/sources/FaceLivenessReactWrapper.tsx +320 -0
  26. package/projects/facecog-liveness-verification/src/lib/components/aws-face-liveness/FaceLivenessReactWrapper.generated.d.ts +28 -0
  27. package/projects/facecog-liveness-verification/src/lib/components/aws-face-liveness/FaceLivenessReactWrapper.generated.js +247 -0
  28. package/projects/facecog-liveness-verification/src/lib/components/aws-face-liveness/FaceLivenessReactWrapper.generated.js.map +1 -0
  29. package/projects/facecog-liveness-verification/src/lib/components/aws-face-liveness/FaceLivenessReactWrapper.js.map +1 -0
  30. package/projects/facecog-liveness-verification/src/lib/components/aws-face-liveness/FaceLivenessReactWrapper.ts +5 -0
  31. package/projects/facecog-liveness-verification/src/lib/components/aws-face-liveness/aws-face-liveness.component.ts +500 -0
  32. package/projects/facecog-liveness-verification/src/lib/components/camera-permission/camera-permission.component.html +41 -0
  33. package/projects/facecog-liveness-verification/src/lib/components/camera-permission/camera-permission.component.scss +234 -0
  34. package/projects/facecog-liveness-verification/src/lib/components/camera-permission/camera-permission.component.spec.ts +158 -0
  35. package/projects/facecog-liveness-verification/src/lib/components/camera-permission/camera-permission.component.ts +58 -0
  36. package/projects/facecog-liveness-verification/src/lib/components/camera-verification/camera-verification.component.html +34 -0
  37. package/projects/facecog-liveness-verification/src/lib/components/camera-verification/camera-verification.component.ts +210 -0
  38. package/projects/facecog-liveness-verification/src/lib/components/dialogs/save-custom-pose-dialog.component.ts +174 -0
  39. package/projects/facecog-liveness-verification/src/lib/components/facetec-scan/facetec-scan.component.html +45 -0
  40. package/projects/facecog-liveness-verification/src/lib/components/facetec-scan/facetec-scan.component.scss +87 -0
  41. package/projects/facecog-liveness-verification/src/lib/components/facetec-scan/facetec-scan.component.ts +182 -0
  42. package/projects/facecog-liveness-verification/src/lib/components/intro/intro.component.html +394 -0
  43. package/projects/facecog-liveness-verification/src/lib/components/intro/intro.component.scss +1567 -0
  44. package/projects/facecog-liveness-verification/src/lib/components/intro/intro.component.spec.ts +699 -0
  45. package/projects/facecog-liveness-verification/src/lib/components/intro/intro.component.ts +721 -0
  46. package/projects/facecog-liveness-verification/src/lib/components/live-preview/live-preview.component.html +120 -0
  47. package/projects/facecog-liveness-verification/src/lib/components/live-preview/live-preview.component.scss +611 -0
  48. package/projects/facecog-liveness-verification/src/lib/components/live-preview/live-preview.component.spec.ts +605 -0
  49. package/projects/facecog-liveness-verification/src/lib/components/live-preview/live-preview.component.ts +524 -0
  50. package/projects/facecog-liveness-verification/src/lib/components/liveness-flow/liveness-flow.component.html +73 -0
  51. package/projects/facecog-liveness-verification/src/lib/components/liveness-flow/liveness-flow.component.scss +19 -0
  52. package/projects/facecog-liveness-verification/src/lib/components/liveness-flow/liveness-flow.component.spec.ts +673 -0
  53. package/projects/facecog-liveness-verification/src/lib/components/liveness-flow/liveness-flow.component.ts +963 -0
  54. package/projects/facecog-liveness-verification/src/lib/components/liveness-verification/liveness-verification.component.html +38 -0
  55. package/projects/facecog-liveness-verification/src/lib/components/liveness-verification/liveness-verification.component.scss +10 -0
  56. package/projects/facecog-liveness-verification/src/lib/components/liveness-verification/liveness-verification.component.ts +233 -0
  57. package/projects/facecog-liveness-verification/src/lib/components/pose-selection/pose-selection.component.html +17 -0
  58. package/projects/facecog-liveness-verification/src/lib/components/pose-selection/pose-selection.component.spec.ts +35 -0
  59. package/projects/facecog-liveness-verification/src/lib/components/pose-selection/pose-selection.component.ts +33 -0
  60. package/projects/facecog-liveness-verification/src/lib/components/processing/processing.component.html +17 -0
  61. package/projects/facecog-liveness-verification/src/lib/components/processing/processing.component.scss +156 -0
  62. package/projects/facecog-liveness-verification/src/lib/components/processing/processing.component.spec.ts +46 -0
  63. package/projects/facecog-liveness-verification/src/lib/components/processing/processing.component.ts +18 -0
  64. package/projects/facecog-liveness-verification/src/lib/components/verification-result/verification-result.component.html +190 -0
  65. package/projects/facecog-liveness-verification/src/lib/components/verification-result/verification-result.component.scss +534 -0
  66. package/projects/facecog-liveness-verification/src/lib/components/verification-result/verification-result.component.spec.ts +286 -0
  67. package/projects/facecog-liveness-verification/src/lib/components/verification-result/verification-result.component.ts +155 -0
  68. package/projects/facecog-liveness-verification/src/lib/interfaces/analyze-response.interface.ts +16 -0
  69. package/projects/facecog-liveness-verification/src/lib/interfaces/aws-face-liveness.interface.ts +46 -0
  70. package/projects/facecog-liveness-verification/src/lib/interfaces/backend-adapter.interface.ts +21 -0
  71. package/projects/facecog-liveness-verification/src/lib/interfaces/backend-http-client.interface.ts +93 -0
  72. package/projects/facecog-liveness-verification/src/lib/interfaces/backend-response.interface.ts +9 -0
  73. package/projects/facecog-liveness-verification/src/lib/interfaces/camera-provider.interface.ts +107 -0
  74. package/projects/facecog-liveness-verification/src/lib/interfaces/category-info.interface.ts +9 -0
  75. package/projects/facecog-liveness-verification/src/lib/interfaces/custom-pose-data.interface.ts +14 -0
  76. package/projects/facecog-liveness-verification/src/lib/interfaces/custom-pose-repository.interface.ts +48 -0
  77. package/projects/facecog-liveness-verification/src/lib/interfaces/custom-pose-response.interface.ts +14 -0
  78. package/projects/facecog-liveness-verification/src/lib/interfaces/index.ts +52 -0
  79. package/projects/facecog-liveness-verification/src/lib/interfaces/liveness-action-result.interface.ts +13 -0
  80. package/projects/facecog-liveness-verification/src/lib/interfaces/liveness-config.interface.ts +17 -0
  81. package/projects/facecog-liveness-verification/src/lib/interfaces/liveness-metadata.interface.ts +17 -0
  82. package/projects/facecog-liveness-verification/src/lib/interfaces/liveness-result.interface.ts +24 -0
  83. package/projects/facecog-liveness-verification/src/lib/interfaces/liveness-verification-config.interface.ts +41 -0
  84. package/projects/facecog-liveness-verification/src/lib/interfaces/multi-backend-analyze-response.interface.ts +21 -0
  85. package/projects/facecog-liveness-verification/src/lib/interfaces/multi-backend-liveness-result.interface.ts +14 -0
  86. package/projects/facecog-liveness-verification/src/lib/interfaces/pose-definition.interface.ts +35 -0
  87. package/projects/facecog-liveness-verification/src/lib/interfaces/pose-keypoint.interface.ts +12 -0
  88. package/projects/facecog-liveness-verification/src/lib/interfaces/pose-match-result.interface.ts +9 -0
  89. package/projects/facecog-liveness-verification/src/lib/interfaces/pose-verify-response.interface.ts +8 -0
  90. package/projects/facecog-liveness-verification/src/lib/interfaces/scan-results.interface.ts +29 -0
  91. package/projects/facecog-liveness-verification/src/lib/interfaces/verification-plan.interface.ts +42 -0
  92. package/projects/facecog-liveness-verification/src/lib/interfaces/verification-progress-event.interface.ts +12 -0
  93. package/projects/facecog-liveness-verification/src/lib/interfaces/verification-session.interface.ts +72 -0
  94. package/projects/facecog-liveness-verification/src/lib/interfaces/verification-step-change-event.interface.ts +11 -0
  95. package/projects/facecog-liveness-verification/src/lib/interfaces/video-recording.interface.ts +9 -0
  96. package/projects/facecog-liveness-verification/src/lib/liveness-verification.module.ts +123 -0
  97. package/projects/facecog-liveness-verification/src/lib/models/constants/aws-face-liveness-component.token.ts +23 -0
  98. package/projects/facecog-liveness-verification/src/lib/models/constants/category-info.constant.ts +14 -0
  99. package/projects/facecog-liveness-verification/src/lib/models/constants/default-liveness-config.constant.ts +18 -0
  100. package/projects/facecog-liveness-verification/src/lib/models/constants/index.ts +5 -0
  101. package/projects/facecog-liveness-verification/src/lib/models/constants/liveness-verification-config.token.ts +16 -0
  102. package/projects/facecog-liveness-verification/src/lib/models/constants/pose-definitions.constant.ts +377 -0
  103. package/projects/facecog-liveness-verification/src/lib/models/index.ts +5 -0
  104. package/projects/facecog-liveness-verification/src/lib/models/utils/index.ts +2 -0
  105. package/projects/facecog-liveness-verification/src/lib/models/utils/pose.utils.spec.ts +76 -0
  106. package/projects/facecog-liveness-verification/src/lib/models/utils/pose.utils.ts +59 -0
  107. package/projects/facecog-liveness-verification/src/lib/services/aws-face-liveness.service.ts +49 -0
  108. package/projects/facecog-liveness-verification/src/lib/services/backend-http.service.spec.ts +111 -0
  109. package/projects/facecog-liveness-verification/src/lib/services/backend-http.service.ts +130 -0
  110. package/projects/facecog-liveness-verification/src/lib/services/backends/azure-backend.service.spec.ts +69 -0
  111. package/projects/facecog-liveness-verification/src/lib/services/backends/azure-backend.service.ts +72 -0
  112. package/projects/facecog-liveness-verification/src/lib/services/backends/facetec-backend.service.spec.ts +24 -0
  113. package/projects/facecog-liveness-verification/src/lib/services/backends/facetec-backend.service.ts +35 -0
  114. package/projects/facecog-liveness-verification/src/lib/services/backends/mock-backend.service.spec.ts +36 -0
  115. package/projects/facecog-liveness-verification/src/lib/services/backends/mock-backend.service.ts +39 -0
  116. package/projects/facecog-liveness-verification/src/lib/services/backends/openpose-backend.service.spec.ts +81 -0
  117. package/projects/facecog-liveness-verification/src/lib/services/backends/openpose-backend.service.ts +72 -0
  118. package/projects/facecog-liveness-verification/src/lib/services/backends/rekognition-analysis-backend.service.spec.ts +69 -0
  119. package/projects/facecog-liveness-verification/src/lib/services/backends/rekognition-analysis-backend.service.ts +83 -0
  120. package/projects/facecog-liveness-verification/src/lib/services/camera.service.spec.ts +200 -0
  121. package/projects/facecog-liveness-verification/src/lib/services/camera.service.ts +155 -0
  122. package/projects/facecog-liveness-verification/src/lib/services/custom-poses-api.service.ts +117 -0
  123. package/projects/facecog-liveness-verification/src/lib/services/index.ts +18 -0
  124. package/projects/facecog-liveness-verification/src/lib/services/liveness-backend.service.spec.ts +103 -0
  125. package/projects/facecog-liveness-verification/src/lib/services/liveness-backend.service.ts +61 -0
  126. package/projects/facecog-liveness-verification/src/lib/services/liveness-config.service.spec.ts +109 -0
  127. package/projects/facecog-liveness-verification/src/lib/services/liveness-config.service.ts +70 -0
  128. package/projects/facecog-liveness-verification/src/lib/services/liveness-orchestrator.service.spec.ts +144 -0
  129. package/projects/facecog-liveness-verification/src/lib/services/liveness-orchestrator.service.ts +162 -0
  130. package/projects/facecog-liveness-verification/src/lib/services/pose-detection/hand-gesture-detection.service.ts +315 -0
  131. package/projects/facecog-liveness-verification/src/lib/services/pose-detection/index.ts +5 -0
  132. package/projects/facecog-liveness-verification/src/lib/services/pose-detection/openpose.service.ts +287 -0
  133. package/projects/facecog-liveness-verification/src/lib/services/pose-detection/pose-comparison.service.ts +353 -0
  134. package/projects/facecog-liveness-verification/src/lib/services/pose-detection/pose-matching.service.ts +2370 -0
  135. package/projects/facecog-liveness-verification/src/lib/services/pose-detection/reference-pose.service.ts +271 -0
  136. package/projects/facecog-liveness-verification/src/lib/services/pose-selection.service.spec.ts +183 -0
  137. package/projects/facecog-liveness-verification/src/lib/services/pose-selection.service.ts +179 -0
  138. package/projects/facecog-liveness-verification/src/lib/services/verification-api.service.spec.ts +159 -0
  139. package/projects/facecog-liveness-verification/src/lib/services/verification-api.service.ts +151 -0
  140. package/projects/facecog-liveness-verification/src/lib/services/verification-plan.service.spec.ts +184 -0
  141. package/projects/facecog-liveness-verification/src/lib/services/verification-plan.service.ts +94 -0
  142. package/projects/facecog-liveness-verification/src/lib/services/video-recorder.service.spec.ts +52 -0
  143. package/projects/facecog-liveness-verification/src/lib/services/video-recorder.service.ts +117 -0
  144. package/projects/facecog-liveness-verification/src/lib/types/detection-strategy.type.ts +5 -0
  145. package/projects/facecog-liveness-verification/src/lib/types/index.ts +7 -0
  146. package/projects/facecog-liveness-verification/src/lib/types/liveness-action.type.ts +31 -0
  147. package/projects/facecog-liveness-verification/src/lib/types/liveness-backend.type.ts +5 -0
  148. package/projects/facecog-liveness-verification/src/lib/types/pose-category.type.ts +5 -0
  149. package/projects/facecog-liveness-verification/src/lib/types/pose-difficulty.type.ts +5 -0
  150. package/projects/facecog-liveness-verification/src/lib/types/verification-flow-step.type.ts +5 -0
  151. package/projects/facecog-liveness-verification/src/lib/types/verification-step-kind.type.ts +4 -0
  152. package/projects/facecog-liveness-verification/src/public-api.ts +150 -0
  153. package/projects/facecog-liveness-verification/tsconfig.lib.json +20 -0
  154. package/projects/facecog-liveness-verification/tsconfig.lib.prod.json +11 -0
  155. package/projects/facecog-liveness-verification/tsconfig.spec.json +13 -0
  156. package/projects/facecog-liveness-verification/tsconfig.wrapper.json +15 -0
  157. package/projects/facecog-liveness-verification-test/src/app/app-routing.module.ts +22 -0
  158. package/projects/facecog-liveness-verification-test/src/app/app.component.html +3 -0
  159. package/projects/facecog-liveness-verification-test/src/app/app.component.scss +0 -0
  160. package/projects/facecog-liveness-verification-test/src/app/app.component.ts +11 -0
  161. package/projects/facecog-liveness-verification-test/src/app/app.module.ts +27 -0
  162. package/projects/facecog-liveness-verification-test/src/app/home/home-routing.module.ts +16 -0
  163. package/projects/facecog-liveness-verification-test/src/app/home/home.module.ts +19 -0
  164. package/projects/facecog-liveness-verification-test/src/app/home/home.page.html +39 -0
  165. package/projects/facecog-liveness-verification-test/src/app/home/home.page.scss +97 -0
  166. package/projects/facecog-liveness-verification-test/src/app/home/home.page.spec.ts +24 -0
  167. package/projects/facecog-liveness-verification-test/src/app/home/home.page.ts +92 -0
  168. package/projects/facecog-liveness-verification-test/src/app/home/verification-modal.component.ts +106 -0
  169. package/projects/facecog-liveness-verification-test/src/assets/fonts/gilroy/Gilroy-Bold_0.ttf +0 -0
  170. package/projects/facecog-liveness-verification-test/src/assets/fonts/gilroy/Gilroy-Medium_0.ttf +0 -0
  171. package/projects/facecog-liveness-verification-test/src/assets/fonts/gilroy/Gilroy-Regular_0.ttf +0 -0
  172. package/projects/facecog-liveness-verification-test/src/assets/fonts/gilroy/Gilroy-SemiBold_0.ttf +0 -0
  173. package/projects/facecog-liveness-verification-test/src/assets/fonts/gilroy/Gilroy-Thin_0.ttf +0 -0
  174. package/projects/facecog-liveness-verification-test/src/assets/icon/favicon.png +0 -0
  175. package/projects/facecog-liveness-verification-test/src/assets/images/poses/Five_Fingers_Left.jpg +0 -0
  176. package/projects/facecog-liveness-verification-test/src/assets/images/poses/Left_Palm.jpg +0 -0
  177. package/projects/facecog-liveness-verification-test/src/assets/images/poses/Ok_Sign_Right.jpg +0 -0
  178. package/projects/facecog-liveness-verification-test/src/assets/images/poses/Peace_Sign_Left.jpg +0 -0
  179. package/projects/facecog-liveness-verification-test/src/assets/images/poses/README.md +77 -0
  180. package/projects/facecog-liveness-verification-test/src/assets/images/poses/Right_Palm.jpg +0 -0
  181. package/projects/facecog-liveness-verification-test/src/assets/images/poses/Speak_Phrase.jpg +0 -0
  182. package/projects/facecog-liveness-verification-test/src/assets/images/poses/Three_Fingers_Right.jpg +0 -0
  183. package/projects/facecog-liveness-verification-test/src/assets/images/poses/Thumbs_Up_Left.jpg +0 -0
  184. package/projects/facecog-liveness-verification-test/src/assets/images/poses/Thumbs_Up_Right.jpg +0 -0
  185. package/projects/facecog-liveness-verification-test/src/assets/images/poses/Wave_Right.jpg +0 -0
  186. package/projects/facecog-liveness-verification-test/src/assets/images/poses/blink.jpeg +0 -0
  187. package/projects/facecog-liveness-verification-test/src/assets/images/poses/blink_twice.jpeg +0 -0
  188. package/projects/facecog-liveness-verification-test/src/assets/images/poses/center_face.png +0 -0
  189. package/projects/facecog-liveness-verification-test/src/assets/images/poses/clap.jpeg +0 -0
  190. package/projects/facecog-liveness-verification-test/src/assets/images/poses/cover_mouth.png +0 -0
  191. package/projects/facecog-liveness-verification-test/src/assets/images/poses/cover_right_eye.png +0 -0
  192. package/projects/facecog-liveness-verification-test/src/assets/images/poses/cross_arms.png +0 -0
  193. package/projects/facecog-liveness-verification-test/src/assets/images/poses/face_straight.png +0 -0
  194. package/projects/facecog-liveness-verification-test/src/assets/images/poses/follow_dot.png +0 -0
  195. package/projects/facecog-liveness-verification-test/src/assets/images/poses/look_down.png +0 -0
  196. package/projects/facecog-liveness-verification-test/src/assets/images/poses/look_up.png +0 -0
  197. package/projects/facecog-liveness-verification-test/src/assets/images/poses/move_closer.png +0 -0
  198. package/projects/facecog-liveness-verification-test/src/assets/images/poses/nod.png +0 -0
  199. package/projects/facecog-liveness-verification-test/src/assets/images/poses/open_mouth.png +0 -0
  200. package/projects/facecog-liveness-verification-test/src/assets/images/poses/raise_eyebrow.png +0 -0
  201. package/projects/facecog-liveness-verification-test/src/assets/images/poses/rotate_face.jpeg +0 -0
  202. package/projects/facecog-liveness-verification-test/src/assets/images/poses/shake_head.jpeg +0 -0
  203. package/projects/facecog-liveness-verification-test/src/assets/images/poses/smile.png +0 -0
  204. package/projects/facecog-liveness-verification-test/src/assets/images/poses/tilt_left.png +0 -0
  205. package/projects/facecog-liveness-verification-test/src/assets/images/poses/tilt_right.png +0 -0
  206. package/projects/facecog-liveness-verification-test/src/assets/images/poses/touch_chin_left.jpg +0 -0
  207. package/projects/facecog-liveness-verification-test/src/assets/images/poses/touch_left_cheek.jpeg +0 -0
  208. package/projects/facecog-liveness-verification-test/src/assets/images/poses/touch_nose_right.png +0 -0
  209. package/projects/facecog-liveness-verification-test/src/assets/images/poses/touch_right_cheek.jpeg +0 -0
  210. package/projects/facecog-liveness-verification-test/src/assets/images/poses/turn_left.png +0 -0
  211. package/projects/facecog-liveness-verification-test/src/assets/images/poses/turn_right.png +0 -0
  212. package/projects/facecog-liveness-verification-test/src/assets/images/poses/wink.jpeg +0 -0
  213. package/projects/facecog-liveness-verification-test/src/assets/images/reference-pose.jpg +0 -0
  214. package/projects/facecog-liveness-verification-test/src/assets/shapes.svg +1 -0
  215. package/projects/facecog-liveness-verification-test/src/environments/environment.prod.ts +4 -0
  216. package/projects/facecog-liveness-verification-test/src/environments/environment.ts +17 -0
  217. package/projects/facecog-liveness-verification-test/src/global.scss +288 -0
  218. package/projects/facecog-liveness-verification-test/src/index.html +31 -0
  219. package/projects/facecog-liveness-verification-test/src/main.ts +6 -0
  220. package/projects/facecog-liveness-verification-test/src/polyfills.ts +55 -0
  221. package/projects/facecog-liveness-verification-test/src/theme/nextsapien-theme.scss +174 -0
  222. package/projects/facecog-liveness-verification-test/src/theme/variables.scss +2 -0
  223. package/projects/facecog-liveness-verification-test/src/zone-flags.ts +6 -0
  224. package/projects/facecog-liveness-verification-test/tsconfig.app.json +15 -0
  225. package/projects/facecog-liveness-verification-test/tsconfig.spec.json +14 -0
  226. package/setup-jest.ts +118 -0
  227. package/tsconfig.json +41 -0
  228. package/tsconfig.spec.json +15 -0
  229. package/vercel.json +24 -0
@@ -0,0 +1,286 @@
1
+ import { ComponentFixture, TestBed } from '@angular/core/testing';
2
+ import { IonicModule } from '@ionic/angular';
3
+ import { CommonModule } from '@angular/common';
4
+ import { DomSanitizer } from '@angular/platform-browser';
5
+
6
+ import { VerificationResultComponent } from './verification-result.component';
7
+ import type { LivenessResult } from '../../interfaces/liveness-result.interface';
8
+ import type { MultiBackendLivenessResult } from '../../interfaces/multi-backend-liveness-result.interface';
9
+ import type { MultiBackendAnalyzeResponse } from '../../interfaces/multi-backend-analyze-response.interface';
10
+ import type { AnalyzeResponse } from '../../interfaces/analyze-response.interface';
11
+
12
+ describe('VerificationResultComponent', () => {
13
+ let component: VerificationResultComponent;
14
+ let fixture: ComponentFixture<VerificationResultComponent>;
15
+
16
+ const baseResult: LivenessResult = {
17
+ success: true,
18
+ confidence: 0.92,
19
+ verifiedImage: 'data:image/jpeg;base64,abc',
20
+ metadata: {
21
+ timestamp: '2025-01-01T00:00:00Z',
22
+ backend: 'amazon' as const,
23
+ confidence: 0.92,
24
+ attemptNumber: 1
25
+ }
26
+ };
27
+
28
+ const failedResult: LivenessResult = {
29
+ ...baseResult,
30
+ success: false,
31
+ error: 'Low confidence'
32
+ };
33
+
34
+ const createAnalyzeResponse = (backend: string, isLive: boolean, confidence: number): AnalyzeResponse => ({
35
+ isLive,
36
+ confidence,
37
+ metadata: {
38
+ backend: backend as any,
39
+ timestamp: new Date(),
40
+ sessionId: 'sess-1'
41
+ }
42
+ });
43
+
44
+ const createMultiBackendResult = (): MultiBackendAnalyzeResponse => ({
45
+ amazon: createAnalyzeResponse('amazon', true, 0.9),
46
+ openpose: createAnalyzeResponse('openpose', true, 0.85),
47
+ facetec: createAnalyzeResponse('facetec', true, 0.88),
48
+ primary: createAnalyzeResponse('amazon', true, 0.9),
49
+ consensus: {
50
+ isLive: true,
51
+ confidence: 0.88,
52
+ votingResults: {
53
+ liveVotes: 3,
54
+ notLiveVotes: 0,
55
+ agreement: 'unanimous'
56
+ }
57
+ }
58
+ });
59
+
60
+ beforeEach(async () => {
61
+ const sanitizerSpy = {
62
+ bypassSecurityTrustUrl: jest.fn((url: string) => url as any),
63
+ bypassSecurityTrustHtml: jest.fn(),
64
+ bypassSecurityTrustStyle: jest.fn(),
65
+ bypassSecurityTrustScript: jest.fn(),
66
+ bypassSecurityTrustResourceUrl: jest.fn(),
67
+ sanitize: jest.fn(),
68
+ };
69
+
70
+ await TestBed.configureTestingModule({
71
+ imports: [CommonModule, IonicModule.forRoot(), VerificationResultComponent],
72
+ providers: [{ provide: DomSanitizer, useValue: sanitizerSpy }]
73
+ }).compileComponents();
74
+
75
+ fixture = TestBed.createComponent(VerificationResultComponent);
76
+ component = fixture.componentInstance;
77
+ component.result = baseResult;
78
+ });
79
+
80
+ afterEach(() => {
81
+ component.ngOnDestroy();
82
+ });
83
+
84
+ it('should create', () => {
85
+ expect(component).toBeTruthy();
86
+ });
87
+
88
+ it('onDone emits doneClicked and complete, clears countdown', () => {
89
+ component.ngOnInit();
90
+ expect(component.countdownActive()).toBe(true);
91
+
92
+ let doneEmitted = false;
93
+ let completeEmitted = false;
94
+ component.doneClicked.subscribe(() => (doneEmitted = true));
95
+ component.complete.subscribe((r) => {
96
+ completeEmitted = true;
97
+ expect(r).toEqual(baseResult);
98
+ });
99
+
100
+ component.onDone();
101
+
102
+ expect(doneEmitted).toBe(true);
103
+ expect(completeEmitted).toBe(true);
104
+ expect(component.countdownActive()).toBe(false);
105
+ });
106
+
107
+ it('onRetry emits retryClicked and retry, clears countdown', () => {
108
+ component.ngOnInit();
109
+
110
+ let retryClickedEmitted = false;
111
+ let retryEmitted = false;
112
+ component.retryClicked.subscribe(() => (retryClickedEmitted = true));
113
+ component.retry.subscribe(() => (retryEmitted = true));
114
+
115
+ component.onRetry();
116
+
117
+ expect(retryClickedEmitted).toBe(true);
118
+ expect(retryEmitted).toBe(true);
119
+ expect(component.countdownActive()).toBe(false);
120
+ });
121
+
122
+ it('confidencePercent returns rounded confidence * 100', () => {
123
+ component.result = { ...baseResult, confidence: 0.876 };
124
+ expect(component.confidencePercent).toBe(88);
125
+ });
126
+
127
+ it('isMultiBackend returns true for multi-backend result', () => {
128
+ const multiResult: MultiBackendLivenessResult = {
129
+ ...baseResult,
130
+ multiBackendResults: createMultiBackendResult(),
131
+ metadata: { timestamp: '', sessionId: '' }
132
+ };
133
+ component.result = multiResult;
134
+ expect(component.isMultiBackend).toBe(true);
135
+ });
136
+
137
+ it('isMultiBackend returns false for single backend result', () => {
138
+ component.result = baseResult;
139
+ expect(component.isMultiBackend).toBe(false);
140
+ });
141
+
142
+ it('multiBackendResult returns result when isMultiBackend', () => {
143
+ const multiResult: MultiBackendLivenessResult = {
144
+ ...baseResult,
145
+ multiBackendResults: createMultiBackendResult(),
146
+ metadata: { timestamp: '', sessionId: '' }
147
+ };
148
+ component.result = multiResult;
149
+ expect(component.multiBackendResult).toEqual(multiResult);
150
+ });
151
+
152
+ it('multiBackendResult returns null when not multi-backend', () => {
153
+ component.result = baseResult;
154
+ expect(component.multiBackendResult).toBeNull();
155
+ });
156
+
157
+ it('getBackendConfidencePercent returns rounded confidence', () => {
158
+ const backend = createAnalyzeResponse('amazon', true, 0.756);
159
+ expect(component.getBackendConfidencePercent(backend)).toBe(76);
160
+ });
161
+
162
+ it('getBackendName returns display names for known backends', () => {
163
+ expect(component.getBackendName('amazon')).toBe('Amazon Rekognition');
164
+ expect(component.getBackendName('openpose')).toBe('OpenPose/MoveNet');
165
+ expect(component.getBackendName('facetec')).toBe('FaceTec 3D Liveness');
166
+ expect(component.getBackendName('azure')).toBe('Azure Face API');
167
+ expect(component.getBackendName('unknown')).toBe('unknown');
168
+ });
169
+
170
+ it('getAgreementBadgeColor returns correct colors', () => {
171
+ expect(component.getAgreementBadgeColor('unanimous')).toBe('success');
172
+ expect(component.getAgreementBadgeColor('majority')).toBe('warning');
173
+ expect(component.getAgreementBadgeColor('split')).toBe('danger');
174
+ expect(component.getAgreementBadgeColor('other')).toBe('medium');
175
+ });
176
+
177
+ it('singleBackendMetadata returns metadata when not multi-backend', () => {
178
+ component.result = baseResult;
179
+ expect(component.singleBackendMetadata).toEqual(baseResult.metadata);
180
+ });
181
+
182
+ it('singleBackendMetadata returns null when multi-backend', () => {
183
+ const multiResult: MultiBackendLivenessResult = {
184
+ ...baseResult,
185
+ multiBackendResults: createMultiBackendResult(),
186
+ metadata: { timestamp: '', sessionId: '' }
187
+ };
188
+ component.result = multiResult;
189
+ expect(component.singleBackendMetadata).toBeNull();
190
+ });
191
+
192
+ it('ngOnInit creates video URL from videoBlob', () => {
193
+ const blob = new Blob(['video'], { type: 'video/mp4' });
194
+ component.result = { ...baseResult, videoBlob: blob };
195
+
196
+ const createObjectURLSpy = jest.spyOn(URL, 'createObjectURL').mockReturnValue('blob:mock-url');
197
+
198
+ component.ngOnInit();
199
+
200
+ expect(createObjectURLSpy).toHaveBeenCalledWith(blob);
201
+ expect(component.videoUrl).toBe('blob:mock-url');
202
+ expect(component.videoSizeMB).toBeCloseTo(blob.size / (1024 * 1024), 5);
203
+
204
+ createObjectURLSpy.mockRestore();
205
+ });
206
+
207
+ it('ngOnDestroy revokes blob URL', () => {
208
+ const blob = new Blob(['video'], { type: 'video/mp4' });
209
+ component.result = { ...baseResult, videoBlob: blob };
210
+ jest.spyOn(URL, 'createObjectURL').mockReturnValue('blob:mock-url');
211
+ const revokeSpy = jest.spyOn(URL, 'revokeObjectURL').mockImplementation();
212
+
213
+ component.ngOnInit();
214
+ component.ngOnDestroy();
215
+
216
+ expect(revokeSpy).toHaveBeenCalledWith('blob:mock-url');
217
+ revokeSpy.mockRestore();
218
+ });
219
+
220
+ it('ngOnInit starts countdown at 5', () => {
221
+ component.ngOnInit();
222
+ expect(component.countdown()).toBe(5);
223
+ expect(component.countdownActive()).toBe(true);
224
+ });
225
+
226
+ it('countdown decrements every second', () => {
227
+ jest.useFakeTimers();
228
+ component.ngOnInit();
229
+ expect(component.countdown()).toBe(5);
230
+
231
+ jest.advanceTimersByTime(1000);
232
+ expect(component.countdown()).toBe(4);
233
+
234
+ jest.advanceTimersByTime(1000);
235
+ expect(component.countdown()).toBe(3);
236
+
237
+ component.ngOnDestroy();
238
+ jest.useRealTimers();
239
+ });
240
+
241
+ it('countdown emits autoComplete on success when reaching 0', () => {
242
+ jest.useFakeTimers();
243
+ component.result = baseResult;
244
+ let emittedResult: LivenessResult | null = null;
245
+ component.autoComplete.subscribe((r) => (emittedResult = r));
246
+
247
+ component.ngOnInit();
248
+ jest.advanceTimersByTime(5000);
249
+
250
+ expect(emittedResult).toEqual(baseResult);
251
+ expect(component.countdownActive()).toBe(false);
252
+ jest.useRealTimers();
253
+ });
254
+
255
+ it('countdown emits autoRetry on failure when reaching 0', () => {
256
+ jest.useFakeTimers();
257
+ component.result = failedResult;
258
+ let retryEmitted = false;
259
+ component.autoRetry.subscribe(() => (retryEmitted = true));
260
+
261
+ component.ngOnInit();
262
+ jest.advanceTimersByTime(5000);
263
+
264
+ expect(retryEmitted).toBe(true);
265
+ expect(component.countdownActive()).toBe(false);
266
+ jest.useRealTimers();
267
+ });
268
+
269
+ it('countdownMessage shows success message', () => {
270
+ component.result = baseResult;
271
+ component.ngOnInit();
272
+ expect(component.countdownMessage).toContain('Verification successful!');
273
+ expect(component.countdownMessage).toContain('5');
274
+ });
275
+
276
+ it('countdownMessage shows failure message', () => {
277
+ component.result = failedResult;
278
+ component.ngOnInit();
279
+ expect(component.countdownMessage).toContain('Verification failed');
280
+ expect(component.countdownMessage).toContain('5');
281
+ });
282
+
283
+ it('poseSpecificMode defaults to false', () => {
284
+ expect(component.poseSpecificMode).toBe(false);
285
+ });
286
+ });
@@ -0,0 +1,155 @@
1
+ import { Component, EventEmitter, Input, Output, OnInit, OnDestroy, signal, ChangeDetectionStrategy } from '@angular/core';
2
+ import { IonicModule } from '@ionic/angular';
3
+ import { CommonModule } from '@angular/common';
4
+ import { DomSanitizer, SafeUrl } from '@angular/platform-browser';
5
+ import { LivenessResult } from '../../interfaces/liveness-result.interface';
6
+ import { MultiBackendLivenessResult } from '../../interfaces/multi-backend-liveness-result.interface';
7
+ import { AnalyzeResponse } from '../../interfaces/analyze-response.interface';
8
+
9
+ const COUNTDOWN_SECONDS = 5;
10
+
11
+ @Component({
12
+ selector: 'lib-verification-result',
13
+ standalone: true,
14
+ imports: [CommonModule, IonicModule],
15
+ templateUrl: './verification-result.component.html',
16
+ styleUrls: ['./verification-result.component.scss'],
17
+ changeDetection: ChangeDetectionStrategy.OnPush
18
+ })
19
+ export class VerificationResultComponent implements OnInit, OnDestroy {
20
+ @Input() result!: LivenessResult | MultiBackendLivenessResult;
21
+ @Input() isProcessing = false;
22
+ @Input() processingProgress = 0;
23
+ @Input() poseSpecificMode = false;
24
+ @Output() doneClicked = new EventEmitter<void>();
25
+ @Output() retryClicked = new EventEmitter<void>();
26
+ @Output() retry = new EventEmitter<void>();
27
+ @Output() complete = new EventEmitter<LivenessResult>();
28
+ @Output() autoRetry = new EventEmitter<void>();
29
+ @Output() autoComplete = new EventEmitter<LivenessResult>();
30
+
31
+ videoUrl: SafeUrl | null = null;
32
+ videoSizeMB: number | null = null;
33
+ readonly countdown = signal(COUNTDOWN_SECONDS);
34
+ readonly countdownActive = signal(false);
35
+ private videoBlobUrl: string | null = null;
36
+ private countdownTimer: ReturnType<typeof setInterval> | null = null;
37
+
38
+ constructor(private sanitizer: DomSanitizer) {}
39
+
40
+ ngOnInit() {
41
+ if (this.result?.videoBlob) {
42
+ this.videoBlobUrl = URL.createObjectURL(this.result.videoBlob);
43
+ this.videoUrl = this.sanitizer.bypassSecurityTrustUrl(this.videoBlobUrl);
44
+ this.videoSizeMB = this.result.videoBlob.size / (1024 * 1024);
45
+ } else if ((this.result as any)?.videoUrl) {
46
+ this.videoUrl = this.sanitizer.bypassSecurityTrustUrl((this.result as any).videoUrl);
47
+ }
48
+
49
+ this.startCountdown();
50
+ }
51
+
52
+ ngOnDestroy() {
53
+ this.clearCountdown();
54
+ if (this.videoBlobUrl) {
55
+ URL.revokeObjectURL(this.videoBlobUrl);
56
+ }
57
+ }
58
+
59
+ private startCountdown(): void {
60
+ if (!this.result) return;
61
+ this.countdown.set(COUNTDOWN_SECONDS);
62
+ this.countdownActive.set(true);
63
+
64
+ this.countdownTimer = setInterval(() => {
65
+ this.countdown.update(v => v - 1);
66
+ if (this.countdown() <= 0) {
67
+ this.clearCountdown();
68
+ this.onCountdownFinished();
69
+ }
70
+ }, 1000);
71
+ }
72
+
73
+ private clearCountdown(): void {
74
+ this.countdownActive.set(false);
75
+ if (this.countdownTimer) {
76
+ clearInterval(this.countdownTimer);
77
+ this.countdownTimer = null;
78
+ }
79
+ }
80
+
81
+ private onCountdownFinished(): void {
82
+ if (this.result.success) {
83
+ this.autoComplete.emit(this.result as LivenessResult);
84
+ } else {
85
+ this.autoRetry.emit();
86
+ }
87
+ }
88
+
89
+ get countdownMessage(): string {
90
+ if (this.result?.success) {
91
+ return `Verification successful! Closing in ${this.countdown()}...`;
92
+ }
93
+ return `Verification failed. Trying again in ${this.countdown()}...`;
94
+ }
95
+
96
+ onDone() {
97
+ this.clearCountdown();
98
+ this.doneClicked.emit();
99
+ if (this.result) {
100
+ this.complete.emit(this.result as LivenessResult);
101
+ }
102
+ }
103
+
104
+ onRetry() {
105
+ this.clearCountdown();
106
+ this.retryClicked.emit();
107
+ this.retry.emit();
108
+ }
109
+
110
+ get confidencePercent(): number {
111
+ return Math.round((this.result?.confidence || 0) * 100);
112
+ }
113
+
114
+ get isMultiBackend(): boolean {
115
+ return this.result && 'multiBackendResults' in this.result;
116
+ }
117
+
118
+ get multiBackendResult(): MultiBackendLivenessResult | null {
119
+ return this.isMultiBackend ? (this.result as MultiBackendLivenessResult) : null;
120
+ }
121
+
122
+ getBackendConfidencePercent(backend: AnalyzeResponse): number {
123
+ return Math.round(backend.confidence * 100);
124
+ }
125
+
126
+ getBackendName(backendType: string): string {
127
+ const names: { [key: string]: string } = {
128
+ amazon: 'Amazon Rekognition',
129
+ openpose: 'OpenPose/MoveNet',
130
+ facetec: 'FaceTec 3D Liveness',
131
+ azure: 'Azure Face API'
132
+ };
133
+ return names[backendType] || backendType;
134
+ }
135
+
136
+ getAgreementBadgeColor(agreement: string): string {
137
+ switch (agreement) {
138
+ case 'unanimous':
139
+ return 'success';
140
+ case 'majority':
141
+ return 'warning';
142
+ case 'split':
143
+ return 'danger';
144
+ default:
145
+ return 'medium';
146
+ }
147
+ }
148
+
149
+ get singleBackendMetadata(): any {
150
+ if (!this.isMultiBackend) {
151
+ return (this.result as LivenessResult).metadata;
152
+ }
153
+ return null;
154
+ }
155
+ }
@@ -0,0 +1,16 @@
1
+ import { LivenessBackend } from '../types/liveness-backend.type';
2
+
3
+ /**
4
+ * Response from a single backend analysis
5
+ */
6
+ export interface AnalyzeResponse {
7
+ isLive: boolean;
8
+ confidence: number;
9
+ metadata: {
10
+ backend: LivenessBackend;
11
+ timestamp: Date;
12
+ sessionId: string;
13
+ };
14
+ error?: string;
15
+ }
16
+
@@ -0,0 +1,46 @@
1
+ /**
2
+ * AWS Face Liveness Session Response
3
+ */
4
+ export interface AwsFaceLivenessSessionResponse {
5
+ success: boolean;
6
+ sessionId: string;
7
+ expiresAt: string;
8
+ instructions?: string;
9
+ error?: string;
10
+ }
11
+
12
+ /**
13
+ * AWS Face Liveness Results Response
14
+ */
15
+ export interface AwsFaceLivenessResultsResponse {
16
+ success: boolean;
17
+ isLive: boolean;
18
+ confidence: number;
19
+ confidencePercent: number;
20
+ metadata: {
21
+ backend: string;
22
+ timestamp: string;
23
+ sessionId: string;
24
+ status?: string;
25
+ referenceImage?: {
26
+ boundingBox?: unknown;
27
+ };
28
+ auditImagesCount?: number;
29
+ };
30
+ error?: string;
31
+ }
32
+
33
+ /**
34
+ * AWS Credentials Response
35
+ */
36
+ export interface AwsCredentialsResponse {
37
+ success: boolean;
38
+ credentials: {
39
+ accessKeyId: string;
40
+ secretAccessKey: string;
41
+ region: string;
42
+ sessionToken?: string;
43
+ };
44
+ warning?: string;
45
+ error?: string;
46
+ }
@@ -0,0 +1,21 @@
1
+ import { Observable } from 'rxjs';
2
+ import { BackendResponse } from './backend-response.interface';
3
+
4
+ export interface IBackendAdapter {
5
+ /**
6
+ * Verify liveness using the backend service
7
+ * @param imageData Base64 encoded image data
8
+ * @param videoBlob Optional video blob for analysis
9
+ */
10
+ verifyLiveness(imageData: string, videoBlob?: Blob): Observable<BackendResponse>;
11
+
12
+ /**
13
+ * Check if the backend is available and configured
14
+ */
15
+ isAvailable(): boolean;
16
+
17
+ /**
18
+ * Get the backend name
19
+ */
20
+ getName(): string;
21
+ }
@@ -0,0 +1,93 @@
1
+ import { Observable } from 'rxjs';
2
+ import { InjectionToken } from '@angular/core';
3
+ import { LivenessBackend } from '../types/liveness-backend.type';
4
+ import { AnalyzeResponse } from './analyze-response.interface';
5
+ import { MultiBackendAnalyzeResponse } from './multi-backend-analyze-response.interface';
6
+
7
+ /**
8
+ * Session response from backend
9
+ */
10
+ export interface SessionResponse {
11
+ sessionId: string;
12
+ backend: LivenessBackend;
13
+ createdAt?: string;
14
+ }
15
+
16
+ /**
17
+ * Interface for backend HTTP client
18
+ * Implement this interface in your app to connect to your backend API
19
+ */
20
+ export interface IBackendHttpClient {
21
+ /**
22
+ * Create a liveness verification session
23
+ * @param backend The backend to use for this session
24
+ */
25
+ createSession(backend: LivenessBackend): Observable<SessionResponse>;
26
+
27
+ /**
28
+ * Analyze liveness using a specific backend
29
+ * @param sessionId The session ID from createSession
30
+ * @param backend The backend to use
31
+ * @param imageData Base64 encoded image
32
+ * @param frames Optional array of base64 frames
33
+ */
34
+ analyzeLiveness(
35
+ sessionId: string,
36
+ backend: LivenessBackend,
37
+ imageData: string,
38
+ frames?: string[]
39
+ ): Observable<AnalyzeResponse>;
40
+
41
+ /**
42
+ * Analyze liveness using all configured backends
43
+ * @param sessionId The session ID
44
+ * @param imageData Base64 encoded image
45
+ */
46
+ analyzeWithAllBackends(
47
+ sessionId: string,
48
+ imageData: string
49
+ ): Observable<MultiBackendAnalyzeResponse>;
50
+
51
+ /**
52
+ * Analyze liveness using selected backends
53
+ * @param sessionId The session ID
54
+ * @param imageData Base64 encoded image
55
+ * @param backends Array of backends to use (e.g., ['amazon', 'openpose'])
56
+ */
57
+ analyzeWithSelectedBackends(
58
+ sessionId: string,
59
+ imageData: string,
60
+ backends: LivenessBackend[]
61
+ ): Observable<MultiBackendAnalyzeResponse>;
62
+
63
+ /**
64
+ * Upload video to storage (e.g., S3)
65
+ * @param videoBlob The video blob to upload
66
+ * @param sessionId The session ID
67
+ */
68
+ uploadVideo(
69
+ videoBlob: Blob,
70
+ sessionId: string
71
+ ): Observable<{ success: boolean; videoUrl: string; sessionId: string }>;
72
+
73
+ /**
74
+ * Upload a base64-encoded image to storage (fallback when video is unavailable)
75
+ * @param base64Image Base64 image data (with or without data URI prefix)
76
+ * @param sessionId The session ID
77
+ */
78
+ uploadBase64Image(
79
+ base64Image: string,
80
+ sessionId: string
81
+ ): Observable<{ success: boolean; videoUrl: string; sessionId: string }>;
82
+ }
83
+
84
+ /**
85
+ * Injection token for the backend HTTP client
86
+ * Provide this in your app module with your implementation
87
+ *
88
+ * @example
89
+ * providers: [
90
+ * { provide: BACKEND_HTTP_CLIENT, useClass: MyBackendHttpService }
91
+ * ]
92
+ */
93
+ export const BACKEND_HTTP_CLIENT = new InjectionToken<IBackendHttpClient>('BACKEND_HTTP_CLIENT');
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Generic backend response for liveness check
3
+ */
4
+ export interface BackendResponse {
5
+ isLive: boolean;
6
+ confidence: number;
7
+ details?: unknown;
8
+ }
9
+