@smileid/usesmileid 12.0.0 → 12.0.2

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 (365) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/README.md +1 -1
  3. package/dist/camera/camera_defaults.d.ts +2 -0
  4. package/dist/camera/camera_defaults.d.ts.map +1 -1
  5. package/dist/camera/camera_defaults.js +2 -0
  6. package/dist/camera/camera_defaults.js.map +1 -1
  7. package/dist/core/exception/agent_mode_with_enhanced_liveness_exception.d.ts +11 -0
  8. package/dist/core/exception/agent_mode_with_enhanced_liveness_exception.d.ts.map +1 -0
  9. package/dist/core/exception/agent_mode_with_enhanced_liveness_exception.js +17 -0
  10. package/dist/core/exception/agent_mode_with_enhanced_liveness_exception.js.map +1 -0
  11. package/dist/core/exception/capture_validation_exceptions.d.ts +1 -0
  12. package/dist/core/exception/capture_validation_exceptions.d.ts.map +1 -1
  13. package/dist/core/exception/capture_validation_exceptions.js +1 -0
  14. package/dist/core/exception/capture_validation_exceptions.js.map +1 -1
  15. package/dist/core/exception/flow_exceptions.d.ts +4 -2
  16. package/dist/core/exception/flow_exceptions.d.ts.map +1 -1
  17. package/dist/core/exception/flow_exceptions.js +3 -2
  18. package/dist/core/exception/flow_exceptions.js.map +1 -1
  19. package/dist/core/exception/index.d.ts +1 -0
  20. package/dist/core/exception/index.d.ts.map +1 -1
  21. package/dist/core/exception/index.js +1 -0
  22. package/dist/core/exception/index.js.map +1 -1
  23. package/dist/core/exception/missing_job_type_exception.d.ts +1 -3
  24. package/dist/core/exception/missing_job_type_exception.d.ts.map +1 -1
  25. package/dist/core/exception/missing_job_type_exception.js +2 -4
  26. package/dist/core/exception/missing_job_type_exception.js.map +1 -1
  27. package/dist/core/exception/use_smile_id_error_code.d.ts +1 -0
  28. package/dist/core/exception/use_smile_id_error_code.d.ts.map +1 -1
  29. package/dist/core/exception/use_smile_id_error_code.js +1 -0
  30. package/dist/core/exception/use_smile_id_error_code.js.map +1 -1
  31. package/dist/core/models/config.d.ts +19 -0
  32. package/dist/core/models/config.d.ts.map +1 -1
  33. package/dist/core/models/document_type.d.ts +1 -1
  34. package/dist/core/models/document_type.d.ts.map +1 -1
  35. package/dist/core/models/document_type.js +2 -2
  36. package/dist/core/models/document_type.js.map +1 -1
  37. package/dist/core/models/global_privacy_control.d.ts +36 -0
  38. package/dist/core/models/global_privacy_control.d.ts.map +1 -0
  39. package/dist/core/models/global_privacy_control.js +39 -0
  40. package/dist/core/models/global_privacy_control.js.map +1 -0
  41. package/dist/core/models/network_config.d.ts +2 -2
  42. package/dist/core/models/network_config.js +2 -2
  43. package/dist/data/api/interceptors/smile_auth_interceptor.d.ts.map +1 -1
  44. package/dist/data/api/interceptors/smile_auth_interceptor.js +3 -17
  45. package/dist/data/api/interceptors/smile_auth_interceptor.js.map +1 -1
  46. package/dist/data/api/smile_id_api.d.ts +5 -1
  47. package/dist/data/api/smile_id_api.d.ts.map +1 -1
  48. package/dist/data/api/smile_id_api.js +30 -27
  49. package/dist/data/api/smile_id_api.js.map +1 -1
  50. package/dist/data/dsl/builder/retry_config_builder.d.ts +4 -4
  51. package/dist/data/dsl/builder/retry_config_builder.d.ts.map +1 -1
  52. package/dist/data/dsl/builder/retry_config_builder.js +6 -6
  53. package/dist/data/dsl/builder/retry_config_builder.js.map +1 -1
  54. package/dist/data/model/job_request.d.ts +28 -12
  55. package/dist/data/model/job_request.d.ts.map +1 -1
  56. package/dist/data/model/token_payload.d.ts +78 -0
  57. package/dist/data/model/token_payload.d.ts.map +1 -0
  58. package/dist/data/model/token_payload.js +132 -0
  59. package/dist/data/model/token_payload.js.map +1 -0
  60. package/dist/data/model/user_details_payload.d.ts +39 -0
  61. package/dist/data/model/user_details_payload.d.ts.map +1 -0
  62. package/dist/data/model/user_details_payload.js +53 -0
  63. package/dist/data/model/user_details_payload.js.map +1 -0
  64. package/dist/data/smile_id_urls.d.ts +1 -1
  65. package/dist/data/smile_id_urls.js +1 -1
  66. package/dist/data/smile_id_urls.js.map +1 -1
  67. package/dist/data/util/retry_util.d.ts +1 -1
  68. package/dist/data/util/retry_util.d.ts.map +1 -1
  69. package/dist/data/util/retry_util.js +5 -0
  70. package/dist/data/util/retry_util.js.map +1 -1
  71. package/dist/data/util/use_smile_id_token_decoder.d.ts +15 -3
  72. package/dist/data/util/use_smile_id_token_decoder.d.ts.map +1 -1
  73. package/dist/data/util/use_smile_id_token_decoder.js +20 -8
  74. package/dist/data/util/use_smile_id_token_decoder.js.map +1 -1
  75. package/dist/index.d.ts +2 -2
  76. package/dist/index.d.ts.map +1 -1
  77. package/dist/index.js +2 -2
  78. package/dist/index.js.map +1 -1
  79. package/dist/l10n/strings_en.d.ts +4 -1
  80. package/dist/l10n/strings_en.d.ts.map +1 -1
  81. package/dist/l10n/strings_en.js +4 -1
  82. package/dist/l10n/strings_en.js.map +1 -1
  83. package/dist/l10n/use_smile_id_localizations.d.ts +10 -0
  84. package/dist/l10n/use_smile_id_localizations.d.ts.map +1 -1
  85. package/dist/l10n/use_smile_id_localizations.js +59 -3
  86. package/dist/l10n/use_smile_id_localizations.js.map +1 -1
  87. package/dist/metadata/builder_configuration.d.ts +5 -0
  88. package/dist/metadata/builder_configuration.d.ts.map +1 -1
  89. package/dist/metadata/builder_configuration.js +1 -0
  90. package/dist/metadata/builder_configuration.js.map +1 -1
  91. package/dist/metadata/metadata_configuration_mappers.d.ts +2 -3
  92. package/dist/metadata/metadata_configuration_mappers.d.ts.map +1 -1
  93. package/dist/metadata/metadata_configuration_mappers.js +13 -6
  94. package/dist/metadata/metadata_configuration_mappers.js.map +1 -1
  95. package/dist/metadata/use_smile_id_metadata_factory.d.ts.map +1 -1
  96. package/dist/metadata/use_smile_id_metadata_factory.js +14 -5
  97. package/dist/metadata/use_smile_id_metadata_factory.js.map +1 -1
  98. package/dist/presentation/components/use_smile_id_button.d.ts.map +1 -1
  99. package/dist/presentation/components/use_smile_id_button.js +8 -2
  100. package/dist/presentation/components/use_smile_id_button.js.map +1 -1
  101. package/dist/presentation/components/use_smile_id_enhanced_smart_selfie_clip.d.ts +5 -2
  102. package/dist/presentation/components/use_smile_id_enhanced_smart_selfie_clip.d.ts.map +1 -1
  103. package/dist/presentation/components/use_smile_id_enhanced_smart_selfie_clip.js +8 -3
  104. package/dist/presentation/components/use_smile_id_enhanced_smart_selfie_clip.js.map +1 -1
  105. package/dist/presentation/components/use_smile_id_instructions_hero.d.ts.map +1 -1
  106. package/dist/presentation/components/use_smile_id_instructions_hero.js +8 -3
  107. package/dist/presentation/components/use_smile_id_instructions_hero.js.map +1 -1
  108. package/dist/presentation/flow/dsl/builder/config_builder.d.ts +16 -0
  109. package/dist/presentation/flow/dsl/builder/config_builder.d.ts.map +1 -1
  110. package/dist/presentation/flow/dsl/builder/config_builder.js +18 -0
  111. package/dist/presentation/flow/dsl/builder/config_builder.js.map +1 -1
  112. package/dist/presentation/flow/dsl/builder/screens_builder.d.ts +6 -12
  113. package/dist/presentation/flow/dsl/builder/screens_builder.d.ts.map +1 -1
  114. package/dist/presentation/flow/dsl/builder/screens_builder.js +7 -12
  115. package/dist/presentation/flow/dsl/builder/screens_builder.js.map +1 -1
  116. package/dist/presentation/flow/dsl/use_smile_id_flow_builder.d.ts.map +1 -1
  117. package/dist/presentation/flow/dsl/use_smile_id_flow_builder.js +23 -1
  118. package/dist/presentation/flow/dsl/use_smile_id_flow_builder.js.map +1 -1
  119. package/dist/presentation/flow/flow_navigation_manager.d.ts +22 -3
  120. package/dist/presentation/flow/flow_navigation_manager.d.ts.map +1 -1
  121. package/dist/presentation/flow/flow_navigation_manager.js +84 -46
  122. package/dist/presentation/flow/flow_navigation_manager.js.map +1 -1
  123. package/dist/presentation/flow/model/instructions_defaults.d.ts.map +1 -1
  124. package/dist/presentation/flow/model/instructions_defaults.js +1 -1
  125. package/dist/presentation/flow/model/instructions_defaults.js.map +1 -1
  126. package/dist/presentation/flow/screen/orchestrated_capture_screen.d.ts.map +1 -1
  127. package/dist/presentation/flow/screen/orchestrated_capture_screen.js +13 -3
  128. package/dist/presentation/flow/screen/orchestrated_capture_screen.js.map +1 -1
  129. package/dist/presentation/flow/screen/orchestrated_consent_screen.d.ts.map +1 -1
  130. package/dist/presentation/flow/screen/orchestrated_consent_screen.js +3 -1
  131. package/dist/presentation/flow/screen/orchestrated_consent_screen.js.map +1 -1
  132. package/dist/presentation/flow/screen/orchestrated_preview_screen.d.ts.map +1 -1
  133. package/dist/presentation/flow/screen/orchestrated_preview_screen.js +0 -8
  134. package/dist/presentation/flow/screen/orchestrated_preview_screen.js.map +1 -1
  135. package/dist/presentation/flow/screen/orchestrated_processing_screen.d.ts.map +1 -1
  136. package/dist/presentation/flow/screen/orchestrated_processing_screen.js +25 -5
  137. package/dist/presentation/flow/screen/orchestrated_processing_screen.js.map +1 -1
  138. package/dist/presentation/flow/use_smile_id_flow.d.ts.map +1 -1
  139. package/dist/presentation/flow/use_smile_id_flow.js +45 -12
  140. package/dist/presentation/flow/use_smile_id_flow.js.map +1 -1
  141. package/dist/presentation/flow/validation/flow_validator.d.ts +16 -2
  142. package/dist/presentation/flow/validation/flow_validator.d.ts.map +1 -1
  143. package/dist/presentation/flow/validation/flow_validator.js +61 -47
  144. package/dist/presentation/flow/validation/flow_validator.js.map +1 -1
  145. package/dist/presentation/flow/validation/job_type_validator.d.ts +7 -0
  146. package/dist/presentation/flow/validation/job_type_validator.d.ts.map +1 -1
  147. package/dist/presentation/flow/validation/job_type_validator.js +52 -27
  148. package/dist/presentation/flow/validation/job_type_validator.js.map +1 -1
  149. package/dist/presentation/flow/validation/user_details_validator.d.ts +9 -0
  150. package/dist/presentation/flow/validation/user_details_validator.d.ts.map +1 -0
  151. package/dist/presentation/flow/validation/user_details_validator.js +40 -0
  152. package/dist/presentation/flow/validation/user_details_validator.js.map +1 -0
  153. package/dist/presentation/screen/helpers/capture_screen_helpers.d.ts.map +1 -1
  154. package/dist/presentation/screen/helpers/capture_screen_helpers.js +1 -0
  155. package/dist/presentation/screen/helpers/capture_screen_helpers.js.map +1 -1
  156. package/dist/presentation/screen/helpers/capture_ui_state.d.ts +6 -6
  157. package/dist/presentation/screen/helpers/capture_ui_state.d.ts.map +1 -1
  158. package/dist/presentation/screen/helpers/capture_ui_state.js +19 -19
  159. package/dist/presentation/screen/helpers/capture_ui_state.js.map +1 -1
  160. package/dist/presentation/screen/helpers/ess_turn_haptics.d.ts +2 -2
  161. package/dist/presentation/screen/helpers/ess_turn_haptics.d.ts.map +1 -1
  162. package/dist/presentation/screen/helpers/ess_turn_haptics.js +6 -6
  163. package/dist/presentation/screen/helpers/ess_turn_haptics.js.map +1 -1
  164. package/dist/presentation/screen/helpers/scan_state_to_overlay_state.d.ts +5 -5
  165. package/dist/presentation/screen/helpers/scan_state_to_overlay_state.d.ts.map +1 -1
  166. package/dist/presentation/screen/helpers/scan_state_to_overlay_state.js +11 -11
  167. package/dist/presentation/screen/helpers/scan_state_to_overlay_state.js.map +1 -1
  168. package/dist/presentation/screen/helpers/use_capture_orientation_lock.d.ts +13 -3
  169. package/dist/presentation/screen/helpers/use_capture_orientation_lock.d.ts.map +1 -1
  170. package/dist/presentation/screen/helpers/use_capture_orientation_lock.js +48 -6
  171. package/dist/presentation/screen/helpers/use_capture_orientation_lock.js.map +1 -1
  172. package/dist/presentation/screen/use_smile_id_capture_screen.d.ts +4 -2
  173. package/dist/presentation/screen/use_smile_id_capture_screen.d.ts.map +1 -1
  174. package/dist/presentation/screen/use_smile_id_capture_screen.js +90 -23
  175. package/dist/presentation/screen/use_smile_id_capture_screen.js.map +1 -1
  176. package/dist/presentation/screen/use_smile_id_consent_screen.d.ts +7 -0
  177. package/dist/presentation/screen/use_smile_id_consent_screen.d.ts.map +1 -1
  178. package/dist/presentation/screen/use_smile_id_consent_screen.js +6 -5
  179. package/dist/presentation/screen/use_smile_id_consent_screen.js.map +1 -1
  180. package/dist/presentation/screen/use_smile_id_document_back_instructions.d.ts.map +1 -1
  181. package/dist/presentation/screen/use_smile_id_document_back_instructions.js +5 -13
  182. package/dist/presentation/screen/use_smile_id_document_back_instructions.js.map +1 -1
  183. package/dist/presentation/screen/use_smile_id_document_preview_screen.js +1 -1
  184. package/dist/presentation/screen/use_smile_id_document_preview_screen.js.map +1 -1
  185. package/dist/presentation/screen/use_smile_id_preview_screen.d.ts +1 -21
  186. package/dist/presentation/screen/use_smile_id_preview_screen.d.ts.map +1 -1
  187. package/dist/presentation/screen/use_smile_id_preview_screen.js +3 -14
  188. package/dist/presentation/screen/use_smile_id_preview_screen.js.map +1 -1
  189. package/dist/presentation/screen/use_smile_id_processing_screen.js +1 -1
  190. package/dist/presentation/screen/use_smile_id_processing_screen.js.map +1 -1
  191. package/dist/presentation/utils/locale_utils.d.ts +10 -4
  192. package/dist/presentation/utils/locale_utils.d.ts.map +1 -1
  193. package/dist/presentation/utils/locale_utils.js +13 -5
  194. package/dist/presentation/utils/locale_utils.js.map +1 -1
  195. package/dist/testing/fake_face_analyzer.d.ts +43 -0
  196. package/dist/testing/fake_face_analyzer.d.ts.map +1 -0
  197. package/dist/testing/fake_face_analyzer.js +52 -0
  198. package/dist/testing/fake_face_analyzer.js.map +1 -0
  199. package/dist/testing/index.d.ts +5 -0
  200. package/dist/testing/index.d.ts.map +1 -0
  201. package/dist/testing/index.js +7 -0
  202. package/dist/testing/index.js.map +1 -0
  203. package/dist/testing/scenario_expectations.d.ts +28 -0
  204. package/dist/testing/scenario_expectations.d.ts.map +1 -0
  205. package/dist/testing/scenario_expectations.js +65 -0
  206. package/dist/testing/scenario_expectations.js.map +1 -0
  207. package/dist/testing/scenario_loader.d.ts +11 -0
  208. package/dist/testing/scenario_loader.d.ts.map +1 -0
  209. package/dist/testing/scenario_loader.js +64 -0
  210. package/dist/testing/scenario_loader.js.map +1 -0
  211. package/dist/testing/scripted_scan_results.d.ts +17 -0
  212. package/dist/testing/scripted_scan_results.d.ts.map +1 -0
  213. package/dist/testing/scripted_scan_results.js +52 -0
  214. package/dist/testing/scripted_scan_results.js.map +1 -0
  215. package/package.json +11 -4
  216. package/src/__tests__/dsl.test.ts +51 -1
  217. package/src/__tests__/react_native_mock.tsx +22 -0
  218. package/src/__tests__/setup_react_native.ts +17 -2
  219. package/src/__tests__/snapshots/__snapshots__/screens_structural.test.tsx.snap +5267 -0
  220. package/src/__tests__/snapshots/screens_structural.test.tsx +230 -0
  221. package/src/camera/__tests__/camera_permissions.test.ts +72 -0
  222. package/src/camera/__tests__/camera_system_focus.test.ts +173 -0
  223. package/src/camera/__tests__/use_smile_id_camera_preview.test.tsx +461 -0
  224. package/src/camera/__tests__/use_smile_id_camera_system.test.ts +103 -0
  225. package/src/camera/__tests__/use_smile_id_frame_stream_hook.test.tsx +229 -0
  226. package/src/camera/camera_defaults.ts +3 -0
  227. package/src/core/exception/__tests__/builder_validation_exceptions.test.ts +81 -0
  228. package/src/core/exception/agent_mode_with_enhanced_liveness_exception.ts +20 -0
  229. package/src/core/exception/capture_validation_exceptions.ts +1 -0
  230. package/src/core/exception/flow_exceptions.test.ts +10 -0
  231. package/src/core/exception/flow_exceptions.ts +3 -2
  232. package/src/core/exception/index.ts +1 -0
  233. package/src/core/exception/missing_job_type_exception.ts +2 -4
  234. package/src/core/exception/use_smile_id_error_code.ts +1 -0
  235. package/src/core/models/__tests__/document_type.test.ts +2 -2
  236. package/src/core/models/__tests__/flow_models.test.ts +26 -0
  237. package/src/core/models/config.ts +22 -0
  238. package/src/core/models/document_type.ts +2 -2
  239. package/src/core/models/global_privacy_control.ts +45 -0
  240. package/src/core/models/network_config.ts +2 -2
  241. package/src/data/api/__tests__/smile_id_api.test.ts +275 -1
  242. package/src/data/api/interceptors/__tests__/credential_header_redaction.test.ts +144 -0
  243. package/src/data/api/interceptors/__tests__/gzip_interceptor.test.ts +83 -0
  244. package/src/data/api/interceptors/smile_auth_interceptor.ts +3 -18
  245. package/src/data/api/smile_id_api.ts +36 -49
  246. package/src/data/compression/__tests__/payload_compressor_real_jpeg.test.ts +6 -2
  247. package/src/data/dsl/__tests__/use_smile_id_network_builder.test.ts +157 -0
  248. package/src/data/dsl/builder/__tests__/config_builders.test.ts +62 -0
  249. package/src/data/dsl/builder/retry_config_builder.ts +6 -6
  250. package/src/data/factory/__tests__/retry_gzip_mac_composition.test.ts +163 -0
  251. package/src/data/factory/__tests__/signed_job_submission_headers.test.ts +1 -1
  252. package/src/data/model/__tests__/token_payload.test.ts +224 -0
  253. package/src/data/model/__tests__/user_details_payload.test.ts +100 -0
  254. package/src/data/model/job_request.ts +27 -12
  255. package/src/data/model/token_payload.ts +182 -0
  256. package/src/data/model/user_details_payload.ts +84 -0
  257. package/src/data/repository/__tests__/network_retries.test.ts +1 -1
  258. package/src/data/repository/__tests__/repository_dispatch.test.ts +366 -0
  259. package/src/data/repository/__tests__/use_smile_id_repository.test.ts +1 -1
  260. package/src/data/security/__tests__/request_canonicalizer.test.ts +132 -0
  261. package/src/data/security/__tests__/signing_crypto.test.ts +203 -0
  262. package/src/data/smile_id_urls.ts +1 -1
  263. package/src/data/util/__tests__/retry_util.test.ts +25 -0
  264. package/src/data/util/__tests__/use_smile_id_token_decoder.test.ts +179 -0
  265. package/src/data/util/retry_util.ts +9 -1
  266. package/src/data/util/use_smile_id_token_decoder.ts +29 -8
  267. package/src/index.ts +6 -4
  268. package/src/l10n/__tests__/use_smile_id_localizations.test.ts +122 -5
  269. package/src/l10n/__tests__/use_smile_id_localizations_provider.test.tsx +112 -0
  270. package/src/l10n/__tests__/use_smile_id_localizations_surface.test.ts +231 -0
  271. package/src/l10n/strings_en.ts +5 -1
  272. package/src/l10n/use_smile_id_localizations.ts +80 -3
  273. package/src/metadata/__tests__/device_orientation_sampling.test.ts +165 -0
  274. package/src/metadata/__tests__/geolocation.test.ts +150 -0
  275. package/src/metadata/__tests__/metadata_configuration_mappers.test.ts +39 -0
  276. package/src/metadata/__tests__/metadata_configuration_objects.test.ts +2 -1
  277. package/src/metadata/__tests__/metadata_device_context.test.ts +3 -3
  278. package/src/metadata/__tests__/metadata_device_os_android.test.ts +18 -0
  279. package/src/metadata/__tests__/metadata_golden_fixture.json +1 -1
  280. package/src/metadata/__tests__/metadata_payload_golden.test.ts +4 -4
  281. package/src/metadata/__tests__/optional_native_modules.test.ts +234 -0
  282. package/src/metadata/__tests__/use_smile_id_metadata.test.ts +1 -1
  283. package/src/metadata/__tests__/use_smile_id_metadata_factory.test.ts +615 -0
  284. package/src/metadata/builder_configuration.ts +6 -0
  285. package/src/metadata/metadata_configuration_mappers.ts +21 -7
  286. package/src/metadata/use_smile_id_metadata_factory.ts +17 -6
  287. package/src/presentation/assets/si_document_green_book_hero_animation.json +1 -4668
  288. package/src/presentation/assets/si_document_hero_animation.json +1 -4799
  289. package/src/presentation/assets/si_document_hero_back_animation.json +1 -2039
  290. package/src/presentation/assets/si_document_passport_hero_animation.json +1 -14491
  291. package/src/presentation/assets/si_ess_all_directions_hero_animation.json +1 -0
  292. package/src/presentation/assets/si_ess_animation_all_directions.json +1 -6589
  293. package/src/presentation/assets/si_selfie_hero_animation.json +1 -1439
  294. package/src/presentation/assets/si_smile_to_capture_animation.json +1 -1439
  295. package/src/presentation/components/__tests__/use_smile_id_content_card.test.tsx +112 -0
  296. package/src/presentation/components/__tests__/use_smile_id_enhanced_smart_selfie_clip.test.tsx +9 -4
  297. package/src/presentation/components/__tests__/use_smile_id_face_oval_image.test.tsx +190 -0
  298. package/src/presentation/components/__tests__/use_smile_id_instructions_hero.test.tsx +44 -0
  299. package/src/presentation/components/__tests__/use_smile_id_learn_more_content.test.tsx +159 -0
  300. package/src/presentation/components/__tests__/use_smile_id_processing_center_indicator.test.tsx +88 -0
  301. package/src/presentation/components/use_smile_id_button.tsx +7 -2
  302. package/src/presentation/components/use_smile_id_enhanced_smart_selfie_clip.tsx +9 -3
  303. package/src/presentation/components/use_smile_id_instructions_hero.tsx +10 -0
  304. package/src/presentation/flow/__tests__/document_flow_navigation.test.ts +3 -3
  305. package/src/presentation/flow/__tests__/flow_navigation_manager.test.ts +372 -1
  306. package/src/presentation/flow/__tests__/use_smile_id_flow.test.tsx +651 -0
  307. package/src/presentation/flow/dsl/__tests__/use_smile_id_builder_component.test.tsx +120 -0
  308. package/src/presentation/flow/dsl/builder/__tests__/config_builder.test.ts +25 -0
  309. package/src/presentation/flow/dsl/builder/config_builder.ts +21 -0
  310. package/src/presentation/flow/dsl/builder/screens_builder.ts +7 -12
  311. package/src/presentation/flow/dsl/use_smile_id_flow_builder.ts +27 -1
  312. package/src/presentation/flow/flow_navigation_manager.ts +108 -93
  313. package/src/presentation/flow/graph/__tests__/screen_renderer.test.tsx +102 -0
  314. package/src/presentation/flow/model/instructions_defaults.ts +1 -1
  315. package/src/presentation/flow/screen/__tests__/orchestrated_capture_screen.test.tsx +836 -0
  316. package/src/presentation/flow/screen/__tests__/orchestrated_consent_screen.test.tsx +165 -0
  317. package/src/presentation/flow/screen/__tests__/orchestrated_instructions_screen.test.tsx +163 -0
  318. package/src/presentation/flow/screen/__tests__/orchestrated_preview_screen.test.tsx +224 -0
  319. package/src/presentation/flow/screen/__tests__/orchestrated_processing_screen.test.tsx +338 -0
  320. package/src/presentation/flow/screen/orchestrated_capture_screen.tsx +18 -3
  321. package/src/presentation/flow/screen/orchestrated_consent_screen.tsx +5 -0
  322. package/src/presentation/flow/screen/orchestrated_preview_screen.tsx +0 -12
  323. package/src/presentation/flow/screen/orchestrated_processing_screen.tsx +42 -5
  324. package/src/presentation/flow/use_smile_id_flow.tsx +63 -12
  325. package/src/presentation/flow/validation/__tests__/flow_validator.test.ts +219 -1
  326. package/src/presentation/flow/validation/__tests__/job_type_validator.test.ts +200 -0
  327. package/src/presentation/flow/validation/flow_validator.ts +85 -57
  328. package/src/presentation/flow/validation/job_type_validator.ts +73 -39
  329. package/src/presentation/flow/validation/user_details_validator.ts +53 -0
  330. package/src/presentation/screen/__tests__/capture_ui_state.test.ts +66 -47
  331. package/src/presentation/screen/__tests__/ess_turn_haptics.test.ts +15 -11
  332. package/src/presentation/screen/__tests__/feedback_copy_table.test.ts +145 -0
  333. package/src/presentation/screen/__tests__/scan_state_to_overlay_state.test.ts +47 -27
  334. package/src/presentation/screen/__tests__/use_smile_id_capture_screen.test.tsx +524 -14
  335. package/src/presentation/screen/__tests__/use_smile_id_document_back_instructions.test.tsx +4 -2
  336. package/src/presentation/screen/__tests__/use_smile_id_permission_screen.test.tsx +68 -0
  337. package/src/presentation/screen/__tests__/use_smile_id_preview_screen.test.tsx +10 -40
  338. package/src/presentation/screen/helpers/__tests__/use_capture_orientation_lock.test.tsx +212 -0
  339. package/src/presentation/screen/helpers/capture_screen_helpers.ts +1 -0
  340. package/src/presentation/screen/helpers/capture_ui_state.ts +27 -27
  341. package/src/presentation/screen/helpers/ess_turn_haptics.ts +9 -9
  342. package/src/presentation/screen/helpers/scan_state_to_overlay_state.ts +13 -13
  343. package/src/presentation/screen/helpers/use_capture_orientation_lock.ts +69 -7
  344. package/src/presentation/screen/use_smile_id_capture_screen.tsx +107 -28
  345. package/src/presentation/screen/use_smile_id_consent_screen.tsx +16 -5
  346. package/src/presentation/screen/use_smile_id_document_back_instructions.tsx +14 -23
  347. package/src/presentation/screen/use_smile_id_document_preview_screen.tsx +1 -1
  348. package/src/presentation/screen/use_smile_id_preview_screen.tsx +13 -45
  349. package/src/presentation/screen/use_smile_id_processing_screen.tsx +1 -1
  350. package/src/presentation/theme/__tests__/use_use_smile_id_fonts.test.tsx +166 -0
  351. package/src/presentation/utils/__tests__/locale_utils.test.ts +46 -5
  352. package/src/presentation/utils/locale_utils.ts +13 -4
  353. package/src/testing/__tests__/fake_face_analyzer.test.ts +42 -0
  354. package/src/testing/__tests__/scenario_expectations.test.ts +110 -0
  355. package/src/testing/__tests__/scenario_loader.test.ts +64 -0
  356. package/src/testing/fake_face_analyzer.ts +82 -0
  357. package/src/testing/index.ts +15 -0
  358. package/src/testing/scenario_expectations.ts +87 -0
  359. package/src/testing/scenario_loader.ts +83 -0
  360. package/src/testing/scripted_scan_results.ts +66 -0
  361. package/dist/presentation/components/use_smile_id_face_silhouette_overlay.d.ts +0 -15
  362. package/dist/presentation/components/use_smile_id_face_silhouette_overlay.d.ts.map +0 -1
  363. package/dist/presentation/components/use_smile_id_face_silhouette_overlay.js +0 -19
  364. package/dist/presentation/components/use_smile_id_face_silhouette_overlay.js.map +0 -1
  365. package/src/presentation/components/use_smile_id_face_silhouette_overlay.tsx +0 -27
@@ -39,6 +39,7 @@ import type {
39
39
  ConsentInformation,
40
40
  UserDetails,
41
41
  } from "../../../core/models/params";
42
+ import type { TokenPayload } from "../../model/token_payload";
42
43
  import { UseSmileIDMetadata } from "../../../metadata/use_smile_id_metadata";
43
44
 
44
45
  type RecordedCall = {
@@ -109,7 +110,7 @@ const consent: ConsentInformation = Object.freeze({
109
110
  // builds this and it travels on every `JobRequest`; the API
110
111
  // serializes `request.metadata` as the `metadata` multipart part.
111
112
  const metadata = new UseSmileIDMetadata({
112
- sdkVersion: "12.0.0",
113
+ sdkVersion: "12.0.2",
113
114
  sdk: "react-native-expo",
114
115
  deviceOs: "",
115
116
  deviceModel: "",
@@ -1071,6 +1072,279 @@ describe("SmileIDAPI response-body parse failures", () => {
1071
1072
  });
1072
1073
  });
1073
1074
 
1075
+ describe("SmileIDAPI — token-provided user details & consent (wire)", () => {
1076
+ const livenessImages: readonly string[] = [
1077
+ "file:///l1.jpg",
1078
+ "file:///l2.jpg",
1079
+ "file:///l3.jpg",
1080
+ "file:///l4.jpg",
1081
+ "file:///l5.jpg",
1082
+ "file:///l6.jpg",
1083
+ "file:///l7.jpg",
1084
+ ];
1085
+
1086
+ const fullUserDetails: UserDetails = {
1087
+ givenNames: "John",
1088
+ lastName: "Doe",
1089
+ email: "john@example.test",
1090
+ phoneNumber: "+254700000000",
1091
+ };
1092
+
1093
+ function tokenPayload(overrides: Partial<TokenPayload> = {}): TokenPayload {
1094
+ return {
1095
+ hasGivenNames: false,
1096
+ hasLastName: false,
1097
+ hasEmail: false,
1098
+ hasPhoneNumber: false,
1099
+ ...overrides,
1100
+ };
1101
+ }
1102
+
1103
+ const fullBinding = tokenPayload({
1104
+ hasGivenNames: true,
1105
+ hasLastName: true,
1106
+ hasEmail: true,
1107
+ hasPhoneNumber: true,
1108
+ });
1109
+
1110
+ const completeTokenConsent = {
1111
+ granted: true,
1112
+ grantedAt: "2026-01-01T09:00:00.000Z",
1113
+ noticeLanguage: "EN",
1114
+ noticePrivacyPolicyUrl: "https://partner.test/privacy",
1115
+ } as const;
1116
+
1117
+ function enrollmentRequest(
1118
+ overrides: Partial<SmartSelfieEnrollmentRequest> = {},
1119
+ ): SmartSelfieEnrollmentRequest {
1120
+ return {
1121
+ jobType: JobType.smartSelfieEnrollment,
1122
+ selfieImage: "file:///selfie.jpg",
1123
+ livenessImages,
1124
+ consent,
1125
+ metadata,
1126
+ expectedLivenessImageCount: 7,
1127
+ userDetails: fullUserDetails,
1128
+ enhanced: false,
1129
+ ...overrides,
1130
+ };
1131
+ }
1132
+
1133
+ it("a partial user_details payload sends only its remaining fields", async () => {
1134
+ // Assembly already dropped the token-bound names (token always wins);
1135
+ // only email/phone ride the wire.
1136
+ const { api, calls } = makeApi();
1137
+ await api.smartSelfieEnrollment(
1138
+ enrollmentRequest({
1139
+ userDetails: {
1140
+ email: "john@example.test",
1141
+ phoneNumber: "+254700000000",
1142
+ },
1143
+ }),
1144
+ );
1145
+ const parts = partsByName(calls[0]!.body);
1146
+ const parsed = JSON.parse(await readJsonPart(parts["user_details"]![0]));
1147
+ expect(parsed).toEqual({
1148
+ email: "john@example.test",
1149
+ phone_number: "+254700000000",
1150
+ });
1151
+ });
1152
+
1153
+ it("omits the user_details part when the request carries no userDetails", async () => {
1154
+ const { api, calls } = makeApi();
1155
+ const { userDetails: _details, ...withoutUserDetails } =
1156
+ enrollmentRequest();
1157
+ await api.smartSelfieEnrollment({
1158
+ ...withoutUserDetails,
1159
+ tokenPayload: fullBinding,
1160
+ });
1161
+ const parts = partsByName(calls[0]!.body);
1162
+ expect(parts["user_details"]).toBeUndefined();
1163
+ });
1164
+
1165
+ it("an empty user_details payload omits the part entirely", async () => {
1166
+ const { api, calls } = makeApi();
1167
+ await api.smartSelfieEnrollment(enrollmentRequest({ userDetails: {} }));
1168
+ const parts = partsByName(calls[0]!.body);
1169
+ expect(parts["user_details"]).toBeUndefined();
1170
+ });
1171
+
1172
+ it("omits the consent part when the request carries no consent (token-complete path)", async () => {
1173
+ const { api, calls } = makeApi();
1174
+ const { consent: _consent, ...withoutConsent } = enrollmentRequest();
1175
+ await api.smartSelfieEnrollment({
1176
+ ...withoutConsent,
1177
+ tokenPayload: {
1178
+ ...tokenPayload(),
1179
+ consent: completeTokenConsent,
1180
+ },
1181
+ });
1182
+ const parts = partsByName(calls[0]!.body);
1183
+ expect(parts["consent"]).toBeUndefined();
1184
+ // The metadata part is unconditional — it must survive the omission.
1185
+ expect(parts["metadata"]).toBeDefined();
1186
+ });
1187
+
1188
+ it("sends a local consent in full even when the token also binds consent", async () => {
1189
+ // Server merges per-subfield with the token winning; the SDK never
1190
+ // trims a locally captured / preset consent.
1191
+ const { api, calls } = makeApi();
1192
+ await api.smartSelfieEnrollment(
1193
+ enrollmentRequest({
1194
+ tokenPayload: {
1195
+ ...tokenPayload(),
1196
+ consent: completeTokenConsent,
1197
+ },
1198
+ }),
1199
+ );
1200
+ const parts = partsByName(calls[0]!.body);
1201
+ const parsed = JSON.parse(await readJsonPart(parts["consent"]![0]));
1202
+ expect(parsed).toEqual({
1203
+ granted: true,
1204
+ granted_at: "2026-04-30T00:00:00.000Z",
1205
+ notice_language: "EN",
1206
+ notice_privacy_policy_url: "https://example.test/p",
1207
+ });
1208
+ });
1209
+
1210
+ it("regression: without a tokenPayload the parts are identical to today", async () => {
1211
+ const { api, calls } = makeApi();
1212
+ await api.smartSelfieEnrollment(enrollmentRequest());
1213
+ const parts = partsByName(calls[0]!.body);
1214
+ const userDetailsParsed = JSON.parse(
1215
+ await readJsonPart(parts["user_details"]![0]),
1216
+ );
1217
+ expect(userDetailsParsed).toEqual({
1218
+ given_names: "John",
1219
+ last_name: "Doe",
1220
+ email: "john@example.test",
1221
+ phone_number: "+254700000000",
1222
+ });
1223
+ const consentParsed = JSON.parse(await readJsonPart(parts["consent"]![0]));
1224
+ expect(consentParsed).toEqual({
1225
+ granted: true,
1226
+ granted_at: "2026-04-30T00:00:00.000Z",
1227
+ notice_language: "EN",
1228
+ notice_privacy_policy_url: "https://example.test/p",
1229
+ });
1230
+ });
1231
+
1232
+ it("keeps the stripped user_details part an untagged text form field", async () => {
1233
+ const { api, calls } = makeApi();
1234
+ await api.smartSelfieEnrollment(
1235
+ enrollmentRequest({
1236
+ tokenPayload: tokenPayload({ hasGivenNames: true }),
1237
+ }),
1238
+ );
1239
+ const parts = partsByName(calls[0]!.body);
1240
+ expectNoJsonContentType(parts["user_details"]![0]);
1241
+ });
1242
+
1243
+ // Every endpoint routes user_details / consent through the same
1244
+ // helpers — pin the omission behavior across all six.
1245
+ const omissionSubmissions: ReadonlyArray<{
1246
+ readonly endpoint: string;
1247
+ readonly submit: (api: SmileIDAPI) => Promise<unknown>;
1248
+ }> = [
1249
+ {
1250
+ endpoint: "/v3/registration",
1251
+ submit: (api) =>
1252
+ api.smartSelfieEnrollment({
1253
+ jobType: JobType.smartSelfieEnrollment,
1254
+ selfieImage: "file:///selfie.jpg",
1255
+ livenessImages,
1256
+ enhanced: false,
1257
+ metadata,
1258
+ expectedLivenessImageCount: 7,
1259
+ tokenPayload: { ...fullBinding, consent: completeTokenConsent },
1260
+ }),
1261
+ },
1262
+ {
1263
+ endpoint: "/v3/authentication",
1264
+ submit: (api) =>
1265
+ api.smartSelfieAuthentication({
1266
+ jobType: JobType.smartSelfieAuthentication,
1267
+ selfieImage: "file:///selfie.jpg",
1268
+ livenessImages,
1269
+ userId: "user-1",
1270
+ enhanced: false,
1271
+ metadata,
1272
+ expectedLivenessImageCount: 7,
1273
+ tokenPayload: { ...fullBinding, consent: completeTokenConsent },
1274
+ }),
1275
+ },
1276
+ {
1277
+ endpoint: "/v3/enhanced_kyc",
1278
+ submit: (api) =>
1279
+ api.enhancedKyc({
1280
+ jobType: JobType.enhancedKyc,
1281
+ params: { idType: "NATIONAL_ID", idNumber: "1", country: "KE" },
1282
+ metadata,
1283
+ tokenPayload: { ...fullBinding, consent: completeTokenConsent },
1284
+ }),
1285
+ },
1286
+ {
1287
+ endpoint: "/v3/biometric_kyc",
1288
+ submit: (api) =>
1289
+ api.biometricKyc({
1290
+ jobType: JobType.biometricKyc,
1291
+ selfieImage: "file:///selfie.jpg",
1292
+ livenessImages,
1293
+ params: {
1294
+ idType: "NATIONAL_ID",
1295
+ idNumber: "1",
1296
+ country: "KE",
1297
+ useEnrolledImage: false,
1298
+ },
1299
+ metadata,
1300
+ expectedLivenessImageCount: 7,
1301
+ tokenPayload: { ...fullBinding, consent: completeTokenConsent },
1302
+ }),
1303
+ },
1304
+ {
1305
+ endpoint: "/v3/document_verification",
1306
+ submit: (api) =>
1307
+ api.documentVerification({
1308
+ jobType: JobType.documentVerification,
1309
+ selfieImage: "file:///selfie.jpg",
1310
+ livenessImages,
1311
+ frontDocument: "file:///front.jpg",
1312
+ country: "KE",
1313
+ metadata,
1314
+ expectedLivenessImageCount: 7,
1315
+ tokenPayload: { ...fullBinding, consent: completeTokenConsent },
1316
+ }),
1317
+ },
1318
+ {
1319
+ endpoint: "/v3/enhanced_document_verification",
1320
+ submit: (api) =>
1321
+ api.enhancedDocumentVerification({
1322
+ jobType: JobType.enhancedDocumentVerification,
1323
+ selfieImage: "file:///selfie.jpg",
1324
+ livenessImages,
1325
+ frontDocument: "file:///front.jpg",
1326
+ country: "KE",
1327
+ idType: "NATIONAL_ID",
1328
+ metadata,
1329
+ expectedLivenessImageCount: 7,
1330
+ tokenPayload: { ...fullBinding, consent: completeTokenConsent },
1331
+ }),
1332
+ },
1333
+ ];
1334
+
1335
+ for (const { endpoint, submit } of omissionSubmissions) {
1336
+ it(`${endpoint} omits user_details and consent on the token-complete path`, async () => {
1337
+ const { api, calls } = makeApi();
1338
+ await submit(api);
1339
+ expect(calls[0]!.url).toBe(endpoint);
1340
+ const parts = partsByName(calls[0]!.body);
1341
+ expect(parts["user_details"]).toBeUndefined();
1342
+ expect(parts["consent"]).toBeUndefined();
1343
+ expect(parts["metadata"]).toBeDefined();
1344
+ });
1345
+ }
1346
+ });
1347
+
1074
1348
  describe("SmileIDAPI signed job opt-in (request MAC + attestation)", () => {
1075
1349
  // An endpoint missing the opt-in flags ships an unsigned job the
1076
1350
  // server rejects — while the interceptors' own tests stay green.
@@ -0,0 +1,144 @@
1
+ import axios, { AxiosHeaders, type InternalAxiosRequestConfig } from "axios";
2
+ import { describe, expect, it, vi, beforeEach, afterEach } from "vitest";
3
+
4
+ import { LogLevel } from "../../../../core/models/network_config";
5
+ import { LoggingConfigBuilder } from "../../../dsl/builder/config_builder";
6
+ import { InterceptorConfigBuilder } from "../../../dsl/builder/interceptor_config_builder";
7
+ import { attachLoggingInterceptor } from "../logging_interceptor";
8
+
9
+ const CANONICAL_CREDENTIAL_HEADERS: ReadonlyArray<
10
+ readonly [name: string, value: string]
11
+ > = [
12
+ ["SmileID-Token", "secret-jwt-value"],
13
+ ["smileid-partner-id", "secret-partner-002"],
14
+ ["SmileID-Api-Key", "secret-api-key"],
15
+ ["smileid-device-nonce", "secret-nonce"],
16
+ ["Authorization", "Bearer secret-bearer"],
17
+ ["Cookie", "session=secret-cookie"],
18
+ ["Set-Cookie", "session=secret-set-cookie"],
19
+ ];
20
+
21
+ function requestHeaders(): AxiosHeaders {
22
+ const headers = new AxiosHeaders();
23
+ for (const [name, value] of CANONICAL_CREDENTIAL_HEADERS) {
24
+ headers.set(name, value);
25
+ }
26
+ headers.set("Content-Type", "multipart/form-data");
27
+ return headers;
28
+ }
29
+
30
+ function invokeRequestFulfilled(
31
+ client: ReturnType<typeof axios.create>,
32
+ ): InternalAxiosRequestConfig {
33
+ const handlers = (
34
+ client.interceptors.request as unknown as {
35
+ handlers: {
36
+ fulfilled?: (
37
+ config: InternalAxiosRequestConfig,
38
+ ) => InternalAxiosRequestConfig;
39
+ }[];
40
+ }
41
+ ).handlers;
42
+ const lastHandler = handlers[handlers.length - 1];
43
+ if (typeof lastHandler?.fulfilled !== "function") {
44
+ throw new Error("No fulfilled request handler found");
45
+ }
46
+ return lastHandler.fulfilled({
47
+ method: "post",
48
+ baseURL: "https://testapi.smileidentity.com",
49
+ url: "/v2/submit-job",
50
+ headers: requestHeaders(),
51
+ } as InternalAxiosRequestConfig);
52
+ }
53
+
54
+ describe("credential headers under the partner-facing logging config", () => {
55
+ let client: ReturnType<typeof axios.create>;
56
+ let consoleLogSpy: ReturnType<typeof vi.spyOn>;
57
+
58
+ beforeEach(() => {
59
+ client = axios.create();
60
+ consoleLogSpy = vi.spyOn(console, "log").mockImplementation(() => {});
61
+ });
62
+
63
+ afterEach(() => {
64
+ consoleLogSpy.mockRestore();
65
+ });
66
+
67
+ function printedOutput(): string {
68
+ return consoleLogSpy.mock.calls
69
+ .map((call) => call.map((arg) => JSON.stringify(arg)).join(" "))
70
+ .join("\n");
71
+ }
72
+
73
+ const configurations: ReadonlyArray<
74
+ readonly [label: string, attach: (client_: typeof client) => void]
75
+ > = [
76
+ [
77
+ "network { config { logging { } } } at default redactHeaders",
78
+ (client_) => {
79
+ const builder = new LoggingConfigBuilder();
80
+ builder.level = LogLevel.headers;
81
+ attachLoggingInterceptor(client_, builder.build());
82
+ },
83
+ ],
84
+ [
85
+ "network { interceptors { logging() } } at default redactHeaders",
86
+ (client_) => {
87
+ const interceptors = new InterceptorConfigBuilder();
88
+ interceptors
89
+ .logging((l) => {
90
+ l.level = LogLevel.headers;
91
+ })
92
+ .attach(client_);
93
+ },
94
+ ],
95
+ ];
96
+
97
+ for (const [label, attach] of configurations) {
98
+ it(`masks every credential header — ${label}`, () => {
99
+ attach(client);
100
+ invokeRequestFulfilled(client);
101
+
102
+ const output = printedOutput();
103
+ expect(output).not.toBe("");
104
+ for (const [name, value] of CANONICAL_CREDENTIAL_HEADERS) {
105
+ expect(output, `${name} leaked its value`).not.toContain(value);
106
+ }
107
+ expect(output).toContain("multipart/form-data");
108
+ });
109
+
110
+ it(`keeps the header names visible so the audit trail survives — ${label}`, () => {
111
+ attach(client);
112
+ invokeRequestFulfilled(client);
113
+
114
+ const output = printedOutput().toLowerCase();
115
+ for (const [name] of CANONICAL_CREDENTIAL_HEADERS) {
116
+ expect(output, `${name} was dropped entirely`).toContain(
117
+ name.toLowerCase(),
118
+ );
119
+ }
120
+ });
121
+ }
122
+
123
+ it("does not print headers at the default verbosity", () => {
124
+ const builder = new LoggingConfigBuilder();
125
+ attachLoggingInterceptor(client, builder.build());
126
+ invokeRequestFulfilled(client);
127
+
128
+ expect(printedOutput()).not.toContain("headers");
129
+ });
130
+
131
+ it("unions the partner's list with the always-redact set rather than replacing it", () => {
132
+ const builder = new LoggingConfigBuilder();
133
+ builder.level = LogLevel.headers;
134
+ builder.redactHeaders = ["content-type"];
135
+ attachLoggingInterceptor(client, builder.build());
136
+ invokeRequestFulfilled(client);
137
+
138
+ const output = printedOutput();
139
+ expect(output).not.toContain("multipart/form-data");
140
+ for (const [, value] of CANONICAL_CREDENTIAL_HEADERS) {
141
+ expect(output).not.toContain(value);
142
+ }
143
+ });
144
+ });
@@ -0,0 +1,83 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import axios, { AxiosHeaders, type InternalAxiosRequestConfig } from "axios";
3
+
4
+ import { createGzipInterceptor } from "../gzip_interceptor";
5
+
6
+ /**
7
+ * Pins `createGzipInterceptor`'s wire shape: it stamps `Accept-Encoding: gzip` on every request
8
+ * (never reading `config.data`), leaves the body unmodified (no compression, no Content-Type/
9
+ * Length), never sets `Content-Encoding`, and overwrites any existing `Accept-Encoding`.
10
+ */
11
+ describe("createGzipInterceptor", () => {
12
+ function attachAndRun(
13
+ config: InternalAxiosRequestConfig,
14
+ ): Promise<InternalAxiosRequestConfig> {
15
+ const client = axios.create();
16
+ createGzipInterceptor().attach(client);
17
+ const handlers = (
18
+ client.interceptors.request as unknown as {
19
+ handlers: {
20
+ fulfilled?: (
21
+ cfg: InternalAxiosRequestConfig,
22
+ ) => InternalAxiosRequestConfig | Promise<InternalAxiosRequestConfig>;
23
+ }[];
24
+ }
25
+ ).handlers;
26
+ const fulfilled = handlers[handlers.length - 1]?.fulfilled;
27
+ if (!fulfilled) throw new Error("gzip interceptor did not register");
28
+ return Promise.resolve(fulfilled(config));
29
+ }
30
+
31
+ it("stamps Accept-Encoding: gzip on a bodyless request", async () => {
32
+ const result = await attachAndRun({
33
+ headers: new AxiosHeaders(),
34
+ } as InternalAxiosRequestConfig);
35
+
36
+ expect(result.headers.get("Accept-Encoding")).toBe("gzip");
37
+ expect(result.data).toBeUndefined();
38
+ });
39
+
40
+ it("stamps the header without touching a JSON string body", async () => {
41
+ const result = await attachAndRun({
42
+ headers: new AxiosHeaders(),
43
+ data: '{"hello":"world"}',
44
+ } as InternalAxiosRequestConfig);
45
+
46
+ expect(result.headers.get("Accept-Encoding")).toBe("gzip");
47
+ // The body is not compressed or otherwise transformed.
48
+ expect(result.data).toBe('{"hello":"world"}');
49
+ expect(result.headers.get("Content-Type")).toBeUndefined();
50
+ });
51
+
52
+ it("stamps the header without touching a multipart FormData body", async () => {
53
+ // A minimal FormData-like stand-in; the interceptor never inspects
54
+ // `config.data`'s shape, so this is enough to prove pass-through.
55
+ const formData = { getParts: () => [] };
56
+ const result = await attachAndRun({
57
+ headers: new AxiosHeaders(),
58
+ data: formData,
59
+ } as unknown as InternalAxiosRequestConfig);
60
+
61
+ expect(result.headers.get("Accept-Encoding")).toBe("gzip");
62
+ expect(result.data).toBe(formData);
63
+ expect(result.headers.get("Content-Type")).toBeUndefined();
64
+ expect(result.headers.get("Content-Length")).toBeUndefined();
65
+ });
66
+
67
+ it("never stamps Content-Encoding — the request body itself is never compressed", async () => {
68
+ const result = await attachAndRun({
69
+ headers: new AxiosHeaders(),
70
+ data: '{"hello":"world"}',
71
+ } as InternalAxiosRequestConfig);
72
+
73
+ expect(result.headers.get("Content-Encoding")).toBeUndefined();
74
+ });
75
+
76
+ it("overwrites an Accept-Encoding value set by an earlier interceptor", async () => {
77
+ const result = await attachAndRun({
78
+ headers: new AxiosHeaders({ "Accept-Encoding": "identity" }),
79
+ } as InternalAxiosRequestConfig);
80
+
81
+ expect(result.headers.get("Accept-Encoding")).toBe("gzip");
82
+ });
83
+ });
@@ -1,5 +1,5 @@
1
1
  import type { AxiosInstance, InternalAxiosRequestConfig } from "axios";
2
- import { Platform } from "react-native";
2
+ import { sourceSdkIdentifier } from "@smileid/usesmileid_bridge";
3
3
 
4
4
  import type { PartnerConfig } from "../../../core/models/network_config";
5
5
  import { currentRequestTimestamp } from "../../security/request_timestamp";
@@ -26,22 +26,7 @@ import type { TokenHolder } from "../auth/token_holder";
26
26
  * by the next outgoing request.
27
27
  */
28
28
 
29
- const SDK_VERSION = "12.0.0";
30
-
31
- /**
32
- * Source-SDK identifier, suffixed with the runtime platform so the server can
33
- * attribute the request and resolve the matching per-SDK signing secret.
34
- */
35
- function sourceSdk(): string {
36
- switch (Platform.OS) {
37
- case "android":
38
- return "react-native-expo (android)";
39
- case "ios":
40
- return "react-native-expo (iOS)";
41
- default:
42
- return "react-native-expo";
43
- }
44
- }
29
+ const SDK_VERSION = "12.0.2"; // x-release-please-version
45
30
 
46
31
  export type SmileAuthInterceptorOptions = {
47
32
  readonly partnerConfig: PartnerConfig;
@@ -73,7 +58,7 @@ export class SmileAuthInterceptor {
73
58
  config: InternalAxiosRequestConfig,
74
59
  ): Promise<InternalAxiosRequestConfig> {
75
60
  config.headers.set("smileid-token", this._tokenHolder.current);
76
- config.headers.set("smileid-source-sdk", sourceSdk());
61
+ config.headers.set("smileid-source-sdk", sourceSdkIdentifier());
77
62
  config.headers.set("smileid-source-sdk-version", SDK_VERSION);
78
63
  config.headers.set("smileid-partner-id", this._partnerConfig.partnerId);
79
64
  if (this._partnerConfig.callbackUrl) {