@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.
- package/CHANGELOG.md +8 -0
- package/README.md +1 -1
- package/dist/camera/camera_defaults.d.ts +2 -0
- package/dist/camera/camera_defaults.d.ts.map +1 -1
- package/dist/camera/camera_defaults.js +2 -0
- package/dist/camera/camera_defaults.js.map +1 -1
- package/dist/core/exception/agent_mode_with_enhanced_liveness_exception.d.ts +11 -0
- package/dist/core/exception/agent_mode_with_enhanced_liveness_exception.d.ts.map +1 -0
- package/dist/core/exception/agent_mode_with_enhanced_liveness_exception.js +17 -0
- package/dist/core/exception/agent_mode_with_enhanced_liveness_exception.js.map +1 -0
- package/dist/core/exception/capture_validation_exceptions.d.ts +1 -0
- package/dist/core/exception/capture_validation_exceptions.d.ts.map +1 -1
- package/dist/core/exception/capture_validation_exceptions.js +1 -0
- package/dist/core/exception/capture_validation_exceptions.js.map +1 -1
- package/dist/core/exception/flow_exceptions.d.ts +4 -2
- package/dist/core/exception/flow_exceptions.d.ts.map +1 -1
- package/dist/core/exception/flow_exceptions.js +3 -2
- package/dist/core/exception/flow_exceptions.js.map +1 -1
- package/dist/core/exception/index.d.ts +1 -0
- package/dist/core/exception/index.d.ts.map +1 -1
- package/dist/core/exception/index.js +1 -0
- package/dist/core/exception/index.js.map +1 -1
- package/dist/core/exception/missing_job_type_exception.d.ts +1 -3
- package/dist/core/exception/missing_job_type_exception.d.ts.map +1 -1
- package/dist/core/exception/missing_job_type_exception.js +2 -4
- package/dist/core/exception/missing_job_type_exception.js.map +1 -1
- package/dist/core/exception/use_smile_id_error_code.d.ts +1 -0
- package/dist/core/exception/use_smile_id_error_code.d.ts.map +1 -1
- package/dist/core/exception/use_smile_id_error_code.js +1 -0
- package/dist/core/exception/use_smile_id_error_code.js.map +1 -1
- package/dist/core/models/config.d.ts +19 -0
- package/dist/core/models/config.d.ts.map +1 -1
- package/dist/core/models/document_type.d.ts +1 -1
- package/dist/core/models/document_type.d.ts.map +1 -1
- package/dist/core/models/document_type.js +2 -2
- package/dist/core/models/document_type.js.map +1 -1
- package/dist/core/models/global_privacy_control.d.ts +36 -0
- package/dist/core/models/global_privacy_control.d.ts.map +1 -0
- package/dist/core/models/global_privacy_control.js +39 -0
- package/dist/core/models/global_privacy_control.js.map +1 -0
- package/dist/core/models/network_config.d.ts +2 -2
- package/dist/core/models/network_config.js +2 -2
- package/dist/data/api/interceptors/smile_auth_interceptor.d.ts.map +1 -1
- package/dist/data/api/interceptors/smile_auth_interceptor.js +3 -17
- package/dist/data/api/interceptors/smile_auth_interceptor.js.map +1 -1
- package/dist/data/api/smile_id_api.d.ts +5 -1
- package/dist/data/api/smile_id_api.d.ts.map +1 -1
- package/dist/data/api/smile_id_api.js +30 -27
- package/dist/data/api/smile_id_api.js.map +1 -1
- package/dist/data/dsl/builder/retry_config_builder.d.ts +4 -4
- package/dist/data/dsl/builder/retry_config_builder.d.ts.map +1 -1
- package/dist/data/dsl/builder/retry_config_builder.js +6 -6
- package/dist/data/dsl/builder/retry_config_builder.js.map +1 -1
- package/dist/data/model/job_request.d.ts +28 -12
- package/dist/data/model/job_request.d.ts.map +1 -1
- package/dist/data/model/token_payload.d.ts +78 -0
- package/dist/data/model/token_payload.d.ts.map +1 -0
- package/dist/data/model/token_payload.js +132 -0
- package/dist/data/model/token_payload.js.map +1 -0
- package/dist/data/model/user_details_payload.d.ts +39 -0
- package/dist/data/model/user_details_payload.d.ts.map +1 -0
- package/dist/data/model/user_details_payload.js +53 -0
- package/dist/data/model/user_details_payload.js.map +1 -0
- package/dist/data/smile_id_urls.d.ts +1 -1
- package/dist/data/smile_id_urls.js +1 -1
- package/dist/data/smile_id_urls.js.map +1 -1
- package/dist/data/util/retry_util.d.ts +1 -1
- package/dist/data/util/retry_util.d.ts.map +1 -1
- package/dist/data/util/retry_util.js +5 -0
- package/dist/data/util/retry_util.js.map +1 -1
- package/dist/data/util/use_smile_id_token_decoder.d.ts +15 -3
- package/dist/data/util/use_smile_id_token_decoder.d.ts.map +1 -1
- package/dist/data/util/use_smile_id_token_decoder.js +20 -8
- package/dist/data/util/use_smile_id_token_decoder.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/l10n/strings_en.d.ts +4 -1
- package/dist/l10n/strings_en.d.ts.map +1 -1
- package/dist/l10n/strings_en.js +4 -1
- package/dist/l10n/strings_en.js.map +1 -1
- package/dist/l10n/use_smile_id_localizations.d.ts +10 -0
- package/dist/l10n/use_smile_id_localizations.d.ts.map +1 -1
- package/dist/l10n/use_smile_id_localizations.js +59 -3
- package/dist/l10n/use_smile_id_localizations.js.map +1 -1
- package/dist/metadata/builder_configuration.d.ts +5 -0
- package/dist/metadata/builder_configuration.d.ts.map +1 -1
- package/dist/metadata/builder_configuration.js +1 -0
- package/dist/metadata/builder_configuration.js.map +1 -1
- package/dist/metadata/metadata_configuration_mappers.d.ts +2 -3
- package/dist/metadata/metadata_configuration_mappers.d.ts.map +1 -1
- package/dist/metadata/metadata_configuration_mappers.js +13 -6
- package/dist/metadata/metadata_configuration_mappers.js.map +1 -1
- package/dist/metadata/use_smile_id_metadata_factory.d.ts.map +1 -1
- package/dist/metadata/use_smile_id_metadata_factory.js +14 -5
- package/dist/metadata/use_smile_id_metadata_factory.js.map +1 -1
- package/dist/presentation/components/use_smile_id_button.d.ts.map +1 -1
- package/dist/presentation/components/use_smile_id_button.js +8 -2
- package/dist/presentation/components/use_smile_id_button.js.map +1 -1
- package/dist/presentation/components/use_smile_id_enhanced_smart_selfie_clip.d.ts +5 -2
- package/dist/presentation/components/use_smile_id_enhanced_smart_selfie_clip.d.ts.map +1 -1
- package/dist/presentation/components/use_smile_id_enhanced_smart_selfie_clip.js +8 -3
- package/dist/presentation/components/use_smile_id_enhanced_smart_selfie_clip.js.map +1 -1
- package/dist/presentation/components/use_smile_id_instructions_hero.d.ts.map +1 -1
- package/dist/presentation/components/use_smile_id_instructions_hero.js +8 -3
- package/dist/presentation/components/use_smile_id_instructions_hero.js.map +1 -1
- package/dist/presentation/flow/dsl/builder/config_builder.d.ts +16 -0
- package/dist/presentation/flow/dsl/builder/config_builder.d.ts.map +1 -1
- package/dist/presentation/flow/dsl/builder/config_builder.js +18 -0
- package/dist/presentation/flow/dsl/builder/config_builder.js.map +1 -1
- package/dist/presentation/flow/dsl/builder/screens_builder.d.ts +6 -12
- package/dist/presentation/flow/dsl/builder/screens_builder.d.ts.map +1 -1
- package/dist/presentation/flow/dsl/builder/screens_builder.js +7 -12
- package/dist/presentation/flow/dsl/builder/screens_builder.js.map +1 -1
- package/dist/presentation/flow/dsl/use_smile_id_flow_builder.d.ts.map +1 -1
- package/dist/presentation/flow/dsl/use_smile_id_flow_builder.js +23 -1
- package/dist/presentation/flow/dsl/use_smile_id_flow_builder.js.map +1 -1
- package/dist/presentation/flow/flow_navigation_manager.d.ts +22 -3
- package/dist/presentation/flow/flow_navigation_manager.d.ts.map +1 -1
- package/dist/presentation/flow/flow_navigation_manager.js +84 -46
- package/dist/presentation/flow/flow_navigation_manager.js.map +1 -1
- package/dist/presentation/flow/model/instructions_defaults.d.ts.map +1 -1
- package/dist/presentation/flow/model/instructions_defaults.js +1 -1
- package/dist/presentation/flow/model/instructions_defaults.js.map +1 -1
- package/dist/presentation/flow/screen/orchestrated_capture_screen.d.ts.map +1 -1
- package/dist/presentation/flow/screen/orchestrated_capture_screen.js +13 -3
- package/dist/presentation/flow/screen/orchestrated_capture_screen.js.map +1 -1
- package/dist/presentation/flow/screen/orchestrated_consent_screen.d.ts.map +1 -1
- package/dist/presentation/flow/screen/orchestrated_consent_screen.js +3 -1
- package/dist/presentation/flow/screen/orchestrated_consent_screen.js.map +1 -1
- package/dist/presentation/flow/screen/orchestrated_preview_screen.d.ts.map +1 -1
- package/dist/presentation/flow/screen/orchestrated_preview_screen.js +0 -8
- package/dist/presentation/flow/screen/orchestrated_preview_screen.js.map +1 -1
- package/dist/presentation/flow/screen/orchestrated_processing_screen.d.ts.map +1 -1
- package/dist/presentation/flow/screen/orchestrated_processing_screen.js +25 -5
- package/dist/presentation/flow/screen/orchestrated_processing_screen.js.map +1 -1
- package/dist/presentation/flow/use_smile_id_flow.d.ts.map +1 -1
- package/dist/presentation/flow/use_smile_id_flow.js +45 -12
- package/dist/presentation/flow/use_smile_id_flow.js.map +1 -1
- package/dist/presentation/flow/validation/flow_validator.d.ts +16 -2
- package/dist/presentation/flow/validation/flow_validator.d.ts.map +1 -1
- package/dist/presentation/flow/validation/flow_validator.js +61 -47
- package/dist/presentation/flow/validation/flow_validator.js.map +1 -1
- package/dist/presentation/flow/validation/job_type_validator.d.ts +7 -0
- package/dist/presentation/flow/validation/job_type_validator.d.ts.map +1 -1
- package/dist/presentation/flow/validation/job_type_validator.js +52 -27
- package/dist/presentation/flow/validation/job_type_validator.js.map +1 -1
- package/dist/presentation/flow/validation/user_details_validator.d.ts +9 -0
- package/dist/presentation/flow/validation/user_details_validator.d.ts.map +1 -0
- package/dist/presentation/flow/validation/user_details_validator.js +40 -0
- package/dist/presentation/flow/validation/user_details_validator.js.map +1 -0
- package/dist/presentation/screen/helpers/capture_screen_helpers.d.ts.map +1 -1
- package/dist/presentation/screen/helpers/capture_screen_helpers.js +1 -0
- package/dist/presentation/screen/helpers/capture_screen_helpers.js.map +1 -1
- package/dist/presentation/screen/helpers/capture_ui_state.d.ts +6 -6
- package/dist/presentation/screen/helpers/capture_ui_state.d.ts.map +1 -1
- package/dist/presentation/screen/helpers/capture_ui_state.js +19 -19
- package/dist/presentation/screen/helpers/capture_ui_state.js.map +1 -1
- package/dist/presentation/screen/helpers/ess_turn_haptics.d.ts +2 -2
- package/dist/presentation/screen/helpers/ess_turn_haptics.d.ts.map +1 -1
- package/dist/presentation/screen/helpers/ess_turn_haptics.js +6 -6
- package/dist/presentation/screen/helpers/ess_turn_haptics.js.map +1 -1
- package/dist/presentation/screen/helpers/scan_state_to_overlay_state.d.ts +5 -5
- package/dist/presentation/screen/helpers/scan_state_to_overlay_state.d.ts.map +1 -1
- package/dist/presentation/screen/helpers/scan_state_to_overlay_state.js +11 -11
- package/dist/presentation/screen/helpers/scan_state_to_overlay_state.js.map +1 -1
- package/dist/presentation/screen/helpers/use_capture_orientation_lock.d.ts +13 -3
- package/dist/presentation/screen/helpers/use_capture_orientation_lock.d.ts.map +1 -1
- package/dist/presentation/screen/helpers/use_capture_orientation_lock.js +48 -6
- package/dist/presentation/screen/helpers/use_capture_orientation_lock.js.map +1 -1
- package/dist/presentation/screen/use_smile_id_capture_screen.d.ts +4 -2
- package/dist/presentation/screen/use_smile_id_capture_screen.d.ts.map +1 -1
- package/dist/presentation/screen/use_smile_id_capture_screen.js +90 -23
- package/dist/presentation/screen/use_smile_id_capture_screen.js.map +1 -1
- package/dist/presentation/screen/use_smile_id_consent_screen.d.ts +7 -0
- package/dist/presentation/screen/use_smile_id_consent_screen.d.ts.map +1 -1
- package/dist/presentation/screen/use_smile_id_consent_screen.js +6 -5
- package/dist/presentation/screen/use_smile_id_consent_screen.js.map +1 -1
- package/dist/presentation/screen/use_smile_id_document_back_instructions.d.ts.map +1 -1
- package/dist/presentation/screen/use_smile_id_document_back_instructions.js +5 -13
- package/dist/presentation/screen/use_smile_id_document_back_instructions.js.map +1 -1
- package/dist/presentation/screen/use_smile_id_document_preview_screen.js +1 -1
- package/dist/presentation/screen/use_smile_id_document_preview_screen.js.map +1 -1
- package/dist/presentation/screen/use_smile_id_preview_screen.d.ts +1 -21
- package/dist/presentation/screen/use_smile_id_preview_screen.d.ts.map +1 -1
- package/dist/presentation/screen/use_smile_id_preview_screen.js +3 -14
- package/dist/presentation/screen/use_smile_id_preview_screen.js.map +1 -1
- package/dist/presentation/screen/use_smile_id_processing_screen.js +1 -1
- package/dist/presentation/screen/use_smile_id_processing_screen.js.map +1 -1
- package/dist/presentation/utils/locale_utils.d.ts +10 -4
- package/dist/presentation/utils/locale_utils.d.ts.map +1 -1
- package/dist/presentation/utils/locale_utils.js +13 -5
- package/dist/presentation/utils/locale_utils.js.map +1 -1
- package/dist/testing/fake_face_analyzer.d.ts +43 -0
- package/dist/testing/fake_face_analyzer.d.ts.map +1 -0
- package/dist/testing/fake_face_analyzer.js +52 -0
- package/dist/testing/fake_face_analyzer.js.map +1 -0
- package/dist/testing/index.d.ts +5 -0
- package/dist/testing/index.d.ts.map +1 -0
- package/dist/testing/index.js +7 -0
- package/dist/testing/index.js.map +1 -0
- package/dist/testing/scenario_expectations.d.ts +28 -0
- package/dist/testing/scenario_expectations.d.ts.map +1 -0
- package/dist/testing/scenario_expectations.js +65 -0
- package/dist/testing/scenario_expectations.js.map +1 -0
- package/dist/testing/scenario_loader.d.ts +11 -0
- package/dist/testing/scenario_loader.d.ts.map +1 -0
- package/dist/testing/scenario_loader.js +64 -0
- package/dist/testing/scenario_loader.js.map +1 -0
- package/dist/testing/scripted_scan_results.d.ts +17 -0
- package/dist/testing/scripted_scan_results.d.ts.map +1 -0
- package/dist/testing/scripted_scan_results.js +52 -0
- package/dist/testing/scripted_scan_results.js.map +1 -0
- package/package.json +11 -4
- package/src/__tests__/dsl.test.ts +51 -1
- package/src/__tests__/react_native_mock.tsx +22 -0
- package/src/__tests__/setup_react_native.ts +17 -2
- package/src/__tests__/snapshots/__snapshots__/screens_structural.test.tsx.snap +5267 -0
- package/src/__tests__/snapshots/screens_structural.test.tsx +230 -0
- package/src/camera/__tests__/camera_permissions.test.ts +72 -0
- package/src/camera/__tests__/camera_system_focus.test.ts +173 -0
- package/src/camera/__tests__/use_smile_id_camera_preview.test.tsx +461 -0
- package/src/camera/__tests__/use_smile_id_camera_system.test.ts +103 -0
- package/src/camera/__tests__/use_smile_id_frame_stream_hook.test.tsx +229 -0
- package/src/camera/camera_defaults.ts +3 -0
- package/src/core/exception/__tests__/builder_validation_exceptions.test.ts +81 -0
- package/src/core/exception/agent_mode_with_enhanced_liveness_exception.ts +20 -0
- package/src/core/exception/capture_validation_exceptions.ts +1 -0
- package/src/core/exception/flow_exceptions.test.ts +10 -0
- package/src/core/exception/flow_exceptions.ts +3 -2
- package/src/core/exception/index.ts +1 -0
- package/src/core/exception/missing_job_type_exception.ts +2 -4
- package/src/core/exception/use_smile_id_error_code.ts +1 -0
- package/src/core/models/__tests__/document_type.test.ts +2 -2
- package/src/core/models/__tests__/flow_models.test.ts +26 -0
- package/src/core/models/config.ts +22 -0
- package/src/core/models/document_type.ts +2 -2
- package/src/core/models/global_privacy_control.ts +45 -0
- package/src/core/models/network_config.ts +2 -2
- package/src/data/api/__tests__/smile_id_api.test.ts +275 -1
- package/src/data/api/interceptors/__tests__/credential_header_redaction.test.ts +144 -0
- package/src/data/api/interceptors/__tests__/gzip_interceptor.test.ts +83 -0
- package/src/data/api/interceptors/smile_auth_interceptor.ts +3 -18
- package/src/data/api/smile_id_api.ts +36 -49
- package/src/data/compression/__tests__/payload_compressor_real_jpeg.test.ts +6 -2
- package/src/data/dsl/__tests__/use_smile_id_network_builder.test.ts +157 -0
- package/src/data/dsl/builder/__tests__/config_builders.test.ts +62 -0
- package/src/data/dsl/builder/retry_config_builder.ts +6 -6
- package/src/data/factory/__tests__/retry_gzip_mac_composition.test.ts +163 -0
- package/src/data/factory/__tests__/signed_job_submission_headers.test.ts +1 -1
- package/src/data/model/__tests__/token_payload.test.ts +224 -0
- package/src/data/model/__tests__/user_details_payload.test.ts +100 -0
- package/src/data/model/job_request.ts +27 -12
- package/src/data/model/token_payload.ts +182 -0
- package/src/data/model/user_details_payload.ts +84 -0
- package/src/data/repository/__tests__/network_retries.test.ts +1 -1
- package/src/data/repository/__tests__/repository_dispatch.test.ts +366 -0
- package/src/data/repository/__tests__/use_smile_id_repository.test.ts +1 -1
- package/src/data/security/__tests__/request_canonicalizer.test.ts +132 -0
- package/src/data/security/__tests__/signing_crypto.test.ts +203 -0
- package/src/data/smile_id_urls.ts +1 -1
- package/src/data/util/__tests__/retry_util.test.ts +25 -0
- package/src/data/util/__tests__/use_smile_id_token_decoder.test.ts +179 -0
- package/src/data/util/retry_util.ts +9 -1
- package/src/data/util/use_smile_id_token_decoder.ts +29 -8
- package/src/index.ts +6 -4
- package/src/l10n/__tests__/use_smile_id_localizations.test.ts +122 -5
- package/src/l10n/__tests__/use_smile_id_localizations_provider.test.tsx +112 -0
- package/src/l10n/__tests__/use_smile_id_localizations_surface.test.ts +231 -0
- package/src/l10n/strings_en.ts +5 -1
- package/src/l10n/use_smile_id_localizations.ts +80 -3
- package/src/metadata/__tests__/device_orientation_sampling.test.ts +165 -0
- package/src/metadata/__tests__/geolocation.test.ts +150 -0
- package/src/metadata/__tests__/metadata_configuration_mappers.test.ts +39 -0
- package/src/metadata/__tests__/metadata_configuration_objects.test.ts +2 -1
- package/src/metadata/__tests__/metadata_device_context.test.ts +3 -3
- package/src/metadata/__tests__/metadata_device_os_android.test.ts +18 -0
- package/src/metadata/__tests__/metadata_golden_fixture.json +1 -1
- package/src/metadata/__tests__/metadata_payload_golden.test.ts +4 -4
- package/src/metadata/__tests__/optional_native_modules.test.ts +234 -0
- package/src/metadata/__tests__/use_smile_id_metadata.test.ts +1 -1
- package/src/metadata/__tests__/use_smile_id_metadata_factory.test.ts +615 -0
- package/src/metadata/builder_configuration.ts +6 -0
- package/src/metadata/metadata_configuration_mappers.ts +21 -7
- package/src/metadata/use_smile_id_metadata_factory.ts +17 -6
- package/src/presentation/assets/si_document_green_book_hero_animation.json +1 -4668
- package/src/presentation/assets/si_document_hero_animation.json +1 -4799
- package/src/presentation/assets/si_document_hero_back_animation.json +1 -2039
- package/src/presentation/assets/si_document_passport_hero_animation.json +1 -14491
- package/src/presentation/assets/si_ess_all_directions_hero_animation.json +1 -0
- package/src/presentation/assets/si_ess_animation_all_directions.json +1 -6589
- package/src/presentation/assets/si_selfie_hero_animation.json +1 -1439
- package/src/presentation/assets/si_smile_to_capture_animation.json +1 -1439
- package/src/presentation/components/__tests__/use_smile_id_content_card.test.tsx +112 -0
- package/src/presentation/components/__tests__/use_smile_id_enhanced_smart_selfie_clip.test.tsx +9 -4
- package/src/presentation/components/__tests__/use_smile_id_face_oval_image.test.tsx +190 -0
- package/src/presentation/components/__tests__/use_smile_id_instructions_hero.test.tsx +44 -0
- package/src/presentation/components/__tests__/use_smile_id_learn_more_content.test.tsx +159 -0
- package/src/presentation/components/__tests__/use_smile_id_processing_center_indicator.test.tsx +88 -0
- package/src/presentation/components/use_smile_id_button.tsx +7 -2
- package/src/presentation/components/use_smile_id_enhanced_smart_selfie_clip.tsx +9 -3
- package/src/presentation/components/use_smile_id_instructions_hero.tsx +10 -0
- package/src/presentation/flow/__tests__/document_flow_navigation.test.ts +3 -3
- package/src/presentation/flow/__tests__/flow_navigation_manager.test.ts +372 -1
- package/src/presentation/flow/__tests__/use_smile_id_flow.test.tsx +651 -0
- package/src/presentation/flow/dsl/__tests__/use_smile_id_builder_component.test.tsx +120 -0
- package/src/presentation/flow/dsl/builder/__tests__/config_builder.test.ts +25 -0
- package/src/presentation/flow/dsl/builder/config_builder.ts +21 -0
- package/src/presentation/flow/dsl/builder/screens_builder.ts +7 -12
- package/src/presentation/flow/dsl/use_smile_id_flow_builder.ts +27 -1
- package/src/presentation/flow/flow_navigation_manager.ts +108 -93
- package/src/presentation/flow/graph/__tests__/screen_renderer.test.tsx +102 -0
- package/src/presentation/flow/model/instructions_defaults.ts +1 -1
- package/src/presentation/flow/screen/__tests__/orchestrated_capture_screen.test.tsx +836 -0
- package/src/presentation/flow/screen/__tests__/orchestrated_consent_screen.test.tsx +165 -0
- package/src/presentation/flow/screen/__tests__/orchestrated_instructions_screen.test.tsx +163 -0
- package/src/presentation/flow/screen/__tests__/orchestrated_preview_screen.test.tsx +224 -0
- package/src/presentation/flow/screen/__tests__/orchestrated_processing_screen.test.tsx +338 -0
- package/src/presentation/flow/screen/orchestrated_capture_screen.tsx +18 -3
- package/src/presentation/flow/screen/orchestrated_consent_screen.tsx +5 -0
- package/src/presentation/flow/screen/orchestrated_preview_screen.tsx +0 -12
- package/src/presentation/flow/screen/orchestrated_processing_screen.tsx +42 -5
- package/src/presentation/flow/use_smile_id_flow.tsx +63 -12
- package/src/presentation/flow/validation/__tests__/flow_validator.test.ts +219 -1
- package/src/presentation/flow/validation/__tests__/job_type_validator.test.ts +200 -0
- package/src/presentation/flow/validation/flow_validator.ts +85 -57
- package/src/presentation/flow/validation/job_type_validator.ts +73 -39
- package/src/presentation/flow/validation/user_details_validator.ts +53 -0
- package/src/presentation/screen/__tests__/capture_ui_state.test.ts +66 -47
- package/src/presentation/screen/__tests__/ess_turn_haptics.test.ts +15 -11
- package/src/presentation/screen/__tests__/feedback_copy_table.test.ts +145 -0
- package/src/presentation/screen/__tests__/scan_state_to_overlay_state.test.ts +47 -27
- package/src/presentation/screen/__tests__/use_smile_id_capture_screen.test.tsx +524 -14
- package/src/presentation/screen/__tests__/use_smile_id_document_back_instructions.test.tsx +4 -2
- package/src/presentation/screen/__tests__/use_smile_id_permission_screen.test.tsx +68 -0
- package/src/presentation/screen/__tests__/use_smile_id_preview_screen.test.tsx +10 -40
- package/src/presentation/screen/helpers/__tests__/use_capture_orientation_lock.test.tsx +212 -0
- package/src/presentation/screen/helpers/capture_screen_helpers.ts +1 -0
- package/src/presentation/screen/helpers/capture_ui_state.ts +27 -27
- package/src/presentation/screen/helpers/ess_turn_haptics.ts +9 -9
- package/src/presentation/screen/helpers/scan_state_to_overlay_state.ts +13 -13
- package/src/presentation/screen/helpers/use_capture_orientation_lock.ts +69 -7
- package/src/presentation/screen/use_smile_id_capture_screen.tsx +107 -28
- package/src/presentation/screen/use_smile_id_consent_screen.tsx +16 -5
- package/src/presentation/screen/use_smile_id_document_back_instructions.tsx +14 -23
- package/src/presentation/screen/use_smile_id_document_preview_screen.tsx +1 -1
- package/src/presentation/screen/use_smile_id_preview_screen.tsx +13 -45
- package/src/presentation/screen/use_smile_id_processing_screen.tsx +1 -1
- package/src/presentation/theme/__tests__/use_use_smile_id_fonts.test.tsx +166 -0
- package/src/presentation/utils/__tests__/locale_utils.test.ts +46 -5
- package/src/presentation/utils/locale_utils.ts +13 -4
- package/src/testing/__tests__/fake_face_analyzer.test.ts +42 -0
- package/src/testing/__tests__/scenario_expectations.test.ts +110 -0
- package/src/testing/__tests__/scenario_loader.test.ts +64 -0
- package/src/testing/fake_face_analyzer.ts +82 -0
- package/src/testing/index.ts +15 -0
- package/src/testing/scenario_expectations.ts +87 -0
- package/src/testing/scenario_loader.ts +83 -0
- package/src/testing/scripted_scan_results.ts +66 -0
- package/dist/presentation/components/use_smile_id_face_silhouette_overlay.d.ts +0 -15
- package/dist/presentation/components/use_smile_id_face_silhouette_overlay.d.ts.map +0 -1
- package/dist/presentation/components/use_smile_id_face_silhouette_overlay.js +0 -19
- package/dist/presentation/components/use_smile_id_face_silhouette_overlay.js.map +0 -1
- package/src/presentation/components/use_smile_id_face_silhouette_overlay.tsx +0 -27
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
import { describe, expect, it, vi } from "vitest";
|
|
2
|
+
import * as React from "react";
|
|
3
|
+
import { create as createRenderer, act } from "react-test-renderer";
|
|
4
|
+
import type {
|
|
5
|
+
DocumentScanResult,
|
|
6
|
+
FaceScanResult,
|
|
7
|
+
} from "@smileid/usesmileid_bridge";
|
|
8
|
+
import { FrameProcessingException } from "@smileid/usesmileid_bridge";
|
|
9
|
+
|
|
10
|
+
import {
|
|
11
|
+
useSmileIDFrameStream,
|
|
12
|
+
type UseSmileIDFrameStream,
|
|
13
|
+
} from "../use_smile_id_frame_stream";
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* React-level companion to `use_smile_id_frame_stream.test.ts` (which
|
|
17
|
+
* pins the pure dispatcher). These tests mount the hook so the ref
|
|
18
|
+
* plumbing — analyzer / callback swaps between renders, the mounted
|
|
19
|
+
* gate, and the memoised handle identity — is actually exercised.
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
const validFaceWirePayload = {
|
|
23
|
+
output: { faces: [], brightness: 0.5 },
|
|
24
|
+
state: { type: "initial" },
|
|
25
|
+
capturedEvents: [],
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
const validDocumentWirePayload = {
|
|
29
|
+
output: { documents: [], brightness: 0.5 },
|
|
30
|
+
state: { type: "found" },
|
|
31
|
+
capturedEvents: [],
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
type FaceAnalyzerStub = Parameters<typeof useSmileIDFrameStream>[0];
|
|
35
|
+
|
|
36
|
+
const faceAnalyzer = { kind: "face" } as unknown as FaceAnalyzerStub;
|
|
37
|
+
const documentAnalyzer = { kind: "document" } as unknown as FaceAnalyzerStub;
|
|
38
|
+
|
|
39
|
+
type HarnessProps = {
|
|
40
|
+
readonly analyzer: FaceAnalyzerStub;
|
|
41
|
+
readonly onResult: (result: FaceScanResult) => void;
|
|
42
|
+
readonly onError?: (error: unknown) => void;
|
|
43
|
+
readonly onHandle: (handle: UseSmileIDFrameStream) => void;
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
function Harness({ analyzer, onResult, onError, onHandle }: HarnessProps) {
|
|
47
|
+
const handle = useSmileIDFrameStream(
|
|
48
|
+
analyzer,
|
|
49
|
+
onResult,
|
|
50
|
+
onError !== undefined ? { onError } : undefined,
|
|
51
|
+
);
|
|
52
|
+
onHandle(handle);
|
|
53
|
+
return null;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
type Rendered = {
|
|
57
|
+
readonly tree: ReturnType<typeof createRenderer>;
|
|
58
|
+
readonly handles: UseSmileIDFrameStream[];
|
|
59
|
+
readonly latest: () => UseSmileIDFrameStream;
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
function mount(props: Omit<HarnessProps, "onHandle">): Rendered {
|
|
63
|
+
const handles: UseSmileIDFrameStream[] = [];
|
|
64
|
+
let tree!: ReturnType<typeof createRenderer>;
|
|
65
|
+
act(() => {
|
|
66
|
+
tree = createRenderer(
|
|
67
|
+
<Harness {...props} onHandle={(handle) => handles.push(handle)} />,
|
|
68
|
+
);
|
|
69
|
+
});
|
|
70
|
+
return {
|
|
71
|
+
tree,
|
|
72
|
+
handles,
|
|
73
|
+
latest: () => handles[handles.length - 1] as UseSmileIDFrameStream,
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function update(
|
|
78
|
+
rendered: Rendered,
|
|
79
|
+
props: Omit<HarnessProps, "onHandle">,
|
|
80
|
+
): void {
|
|
81
|
+
act(() => {
|
|
82
|
+
rendered.tree.update(
|
|
83
|
+
<Harness
|
|
84
|
+
{...props}
|
|
85
|
+
onHandle={(handle) => rendered.handles.push(handle)}
|
|
86
|
+
/>,
|
|
87
|
+
);
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
describe("useSmileIDFrameStream", () => {
|
|
92
|
+
it("validates the raw wire payload and forwards the typed face result", () => {
|
|
93
|
+
const onResult = vi.fn();
|
|
94
|
+
const rendered = mount({ analyzer: faceAnalyzer, onResult });
|
|
95
|
+
|
|
96
|
+
act(() => {
|
|
97
|
+
rendered.latest().onFrameResult(validFaceWirePayload);
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
expect(onResult).toHaveBeenCalledTimes(1);
|
|
101
|
+
const result = onResult.mock.calls[0]?.[0] as FaceScanResult;
|
|
102
|
+
expect(result.state.type).toBe("initial");
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
it("parses against the document schema when the analyzer is a document one", () => {
|
|
106
|
+
const onResult = vi.fn();
|
|
107
|
+
const rendered = mount({
|
|
108
|
+
analyzer: documentAnalyzer,
|
|
109
|
+
onResult: onResult as unknown as (result: FaceScanResult) => void,
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
act(() => {
|
|
113
|
+
rendered.latest().onFrameResult(validDocumentWirePayload);
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
const result = onResult.mock.calls[0]?.[0] as DocumentScanResult;
|
|
117
|
+
expect(result.state.type).toBe("found");
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
it("keeps a stable handle across re-renders so the frame processor is not rebuilt", () => {
|
|
121
|
+
const onResult = vi.fn();
|
|
122
|
+
const rendered = mount({ analyzer: faceAnalyzer, onResult });
|
|
123
|
+
const first = rendered.latest();
|
|
124
|
+
|
|
125
|
+
update(rendered, { analyzer: faceAnalyzer, onResult: vi.fn() });
|
|
126
|
+
|
|
127
|
+
expect(rendered.latest()).toBe(first);
|
|
128
|
+
expect(rendered.latest().onFrameResult).toBe(first.onFrameResult);
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
it("routes results to the latest onResult after a swap", () => {
|
|
132
|
+
const first = vi.fn();
|
|
133
|
+
const second = vi.fn();
|
|
134
|
+
const rendered = mount({ analyzer: faceAnalyzer, onResult: first });
|
|
135
|
+
|
|
136
|
+
update(rendered, { analyzer: faceAnalyzer, onResult: second });
|
|
137
|
+
act(() => {
|
|
138
|
+
rendered.latest().onFrameResult(validFaceWirePayload);
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
expect(first).not.toHaveBeenCalled();
|
|
142
|
+
expect(second).toHaveBeenCalledTimes(1);
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
it("stops dispatching once the analyzer is detached", () => {
|
|
146
|
+
const onResult = vi.fn();
|
|
147
|
+
const rendered = mount({ analyzer: faceAnalyzer, onResult });
|
|
148
|
+
|
|
149
|
+
update(rendered, { analyzer: null, onResult });
|
|
150
|
+
act(() => {
|
|
151
|
+
rendered.latest().onFrameResult(validFaceWirePayload);
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
expect(onResult).not.toHaveBeenCalled();
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
it("reports a native error marker through the latest onError", () => {
|
|
158
|
+
const onResult = vi.fn();
|
|
159
|
+
const firstOnError = vi.fn();
|
|
160
|
+
const secondOnError = vi.fn();
|
|
161
|
+
const rendered = mount({
|
|
162
|
+
analyzer: faceAnalyzer,
|
|
163
|
+
onResult,
|
|
164
|
+
onError: firstOnError,
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
update(rendered, {
|
|
168
|
+
analyzer: faceAnalyzer,
|
|
169
|
+
onResult,
|
|
170
|
+
onError: secondOnError,
|
|
171
|
+
});
|
|
172
|
+
act(() => {
|
|
173
|
+
rendered.latest().onFrameResult({ error: "session crashed" });
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
expect(firstOnError).not.toHaveBeenCalled();
|
|
177
|
+
expect(secondOnError).toHaveBeenCalledTimes(1);
|
|
178
|
+
expect(secondOnError.mock.calls[0]?.[0]).toBeInstanceOf(
|
|
179
|
+
FrameProcessingException,
|
|
180
|
+
);
|
|
181
|
+
expect(onResult).not.toHaveBeenCalled();
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
it("swallows a schema rejection when no error handler is supplied", () => {
|
|
185
|
+
const onResult = vi.fn();
|
|
186
|
+
const rendered = mount({ analyzer: faceAnalyzer, onResult });
|
|
187
|
+
|
|
188
|
+
expect(() => {
|
|
189
|
+
act(() => {
|
|
190
|
+
rendered.latest().onFrameResult({ nonsense: true });
|
|
191
|
+
});
|
|
192
|
+
}).not.toThrow();
|
|
193
|
+
expect(onResult).not.toHaveBeenCalled();
|
|
194
|
+
});
|
|
195
|
+
|
|
196
|
+
it("drops results that arrive after unmount", () => {
|
|
197
|
+
const onResult = vi.fn();
|
|
198
|
+
const onError = vi.fn();
|
|
199
|
+
const rendered = mount({ analyzer: faceAnalyzer, onResult, onError });
|
|
200
|
+
const handle = rendered.latest();
|
|
201
|
+
|
|
202
|
+
act(() => {
|
|
203
|
+
rendered.tree.unmount();
|
|
204
|
+
});
|
|
205
|
+
handle.onFrameResult(validFaceWirePayload);
|
|
206
|
+
handle.onFrameResult({ error: "late failure" });
|
|
207
|
+
|
|
208
|
+
expect(onResult).not.toHaveBeenCalled();
|
|
209
|
+
expect(onError).not.toHaveBeenCalled();
|
|
210
|
+
});
|
|
211
|
+
|
|
212
|
+
it("gates re-entrant dispatch while a frame is in flight", () => {
|
|
213
|
+
const seen: string[] = [];
|
|
214
|
+
let handle: UseSmileIDFrameStream | null = null;
|
|
215
|
+
const onResult = vi.fn(() => {
|
|
216
|
+
seen.push("outer");
|
|
217
|
+
// A second frame arriving mid-dispatch must be dropped, not recursed into.
|
|
218
|
+
handle?.onFrameResult(validFaceWirePayload);
|
|
219
|
+
});
|
|
220
|
+
const rendered = mount({ analyzer: faceAnalyzer, onResult });
|
|
221
|
+
handle = rendered.latest();
|
|
222
|
+
|
|
223
|
+
act(() => {
|
|
224
|
+
handle?.onFrameResult(validFaceWirePayload);
|
|
225
|
+
});
|
|
226
|
+
|
|
227
|
+
expect(seen).toEqual(["outer"]);
|
|
228
|
+
});
|
|
229
|
+
});
|
|
@@ -12,6 +12,9 @@ export const CameraDefaults = {
|
|
|
12
12
|
/** Document analysis resolution (16:9, matched to the visible preview so the guide-rect crop stays aligned). */
|
|
13
13
|
documentAnalysisResolution: { width: 1280, height: 720 } as const,
|
|
14
14
|
|
|
15
|
+
/** How long a streaming capture waits for its first analyzed frame before reporting the camera unavailable. */
|
|
16
|
+
firstFrameTimeoutMs: 10_000,
|
|
17
|
+
|
|
15
18
|
/** Longest-edge ceiling (px) for an imported document image; downscale-only. */
|
|
16
19
|
documentMaxDimension: 1600,
|
|
17
20
|
/** JPEG quality (0–1) for imported document images. */
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
|
2
|
+
|
|
3
|
+
import { DuplicateScreenTypeException } from "../duplicate_screen_type_exception";
|
|
4
|
+
import { InvalidMissingCaptureTypeException } from "../invalid_missing_capture_type_exception";
|
|
5
|
+
import { InvalidSelfieCaptureConfigException } from "../invalid_selfie_capture_config_exception";
|
|
6
|
+
import { LivenessFrameCountException } from "../liveness_frame_count_exception";
|
|
7
|
+
import { UseSmileIDErrorCode } from "../use_smile_id_error_code";
|
|
8
|
+
|
|
9
|
+
/** Typed builder/validation exceptions: pin `errorCode`, message, and `errorDetails`. */
|
|
10
|
+
describe("DuplicateScreenTypeException", () => {
|
|
11
|
+
it("names the duplicated type + indices and freezes the details", () => {
|
|
12
|
+
const exception = new DuplicateScreenTypeException({
|
|
13
|
+
screenType: "consent",
|
|
14
|
+
indices: [0, 3],
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
expect(exception).toBeInstanceOf(Error);
|
|
18
|
+
expect(exception.errorCode).toBe(
|
|
19
|
+
UseSmileIDErrorCode.Builder.DuplicateScreenType,
|
|
20
|
+
);
|
|
21
|
+
expect(exception.message).toContain("consent");
|
|
22
|
+
expect(exception.message).toContain("0, 3");
|
|
23
|
+
expect(exception.errorDetails).toEqual({
|
|
24
|
+
screenType: "consent",
|
|
25
|
+
indices: [0, 3],
|
|
26
|
+
});
|
|
27
|
+
expect(Object.isFrozen(exception.errorDetails?.["indices"])).toBe(true);
|
|
28
|
+
});
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
describe("LivenessFrameCountException", () => {
|
|
32
|
+
it("reports expected vs actual frame counts", () => {
|
|
33
|
+
const exception = new LivenessFrameCountException({
|
|
34
|
+
expected: 8,
|
|
35
|
+
actual: 3,
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
expect(exception.errorCode).toBe(
|
|
39
|
+
UseSmileIDErrorCode.Validation.ConstraintViolation,
|
|
40
|
+
);
|
|
41
|
+
expect(exception.message).toContain("8");
|
|
42
|
+
expect(exception.message).toContain("3");
|
|
43
|
+
expect(exception.errorDetails).toEqual({ expected: 8, actual: 3 });
|
|
44
|
+
});
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
describe("InvalidSelfieCaptureConfigException", () => {
|
|
48
|
+
it("omits the reason suffix and details when no reason is given", () => {
|
|
49
|
+
const exception = new InvalidSelfieCaptureConfigException();
|
|
50
|
+
|
|
51
|
+
expect(exception.errorCode).toBe(
|
|
52
|
+
UseSmileIDErrorCode.Builder.InvalidSelfieCaptureConfig,
|
|
53
|
+
);
|
|
54
|
+
expect(exception.message).toContain("configuration is missing");
|
|
55
|
+
expect(exception.errorDetails).toBeUndefined();
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
it("appends the reason and carries it in details when provided", () => {
|
|
59
|
+
const exception = new InvalidSelfieCaptureConfigException({
|
|
60
|
+
reason: "minConfidence out of range",
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
expect(exception.message).toContain("minConfidence out of range");
|
|
64
|
+
expect(exception.errorDetails).toEqual({
|
|
65
|
+
reason: "minConfidence out of range",
|
|
66
|
+
});
|
|
67
|
+
});
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
describe("InvalidMissingCaptureTypeException", () => {
|
|
71
|
+
it("carries the missing-capture-type code and an actionable fix", () => {
|
|
72
|
+
const exception = new InvalidMissingCaptureTypeException();
|
|
73
|
+
|
|
74
|
+
expect(exception).toBeInstanceOf(Error);
|
|
75
|
+
expect(exception.errorCode).toBe(
|
|
76
|
+
UseSmileIDErrorCode.Builder.MissingCaptureType,
|
|
77
|
+
);
|
|
78
|
+
expect(exception.message).toContain("captureType is missing");
|
|
79
|
+
expect(exception.suggestedFix).toContain("selfie or document");
|
|
80
|
+
});
|
|
81
|
+
});
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { UseSmileIDBuilderException } from "./use_smile_id_builder_exception";
|
|
2
|
+
import { UseSmileIDErrorCode } from "./use_smile_id_error_code";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Agent mode was combined with enhanced liveness. The head-turn challenge is
|
|
6
|
+
* validated for front-camera capture only, so the two options are mutually
|
|
7
|
+
* exclusive.
|
|
8
|
+
*/
|
|
9
|
+
export class AgentModeWithEnhancedLivenessException extends UseSmileIDBuilderException {
|
|
10
|
+
readonly errorCode =
|
|
11
|
+
UseSmileIDErrorCode.Builder.AgentModeWithEnhancedLiveness;
|
|
12
|
+
|
|
13
|
+
constructor() {
|
|
14
|
+
super({
|
|
15
|
+
message: "allowAgentMode is not supported with enableEnhancedLiveness",
|
|
16
|
+
suggestedFix:
|
|
17
|
+
"Disable one of them inside selfie { }: allowAgentMode for rear-camera agent capture, or enableEnhancedLiveness for the head-turn challenge",
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
}
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
* Each concrete class lives in its own file; this module keeps the
|
|
4
4
|
* legacy import path stable.
|
|
5
5
|
*/
|
|
6
|
+
export { AgentModeWithEnhancedLivenessException } from "./agent_mode_with_enhanced_liveness_exception";
|
|
6
7
|
export { InvalidSelfieCaptureConfigException } from "./invalid_selfie_capture_config_exception";
|
|
7
8
|
export { InvalidDocumentCaptureConfigException } from "./invalid_document_capture_config_exception";
|
|
8
9
|
export { InvalidMissingCaptureTypeException } from "./invalid_missing_capture_type_exception";
|
|
@@ -36,4 +36,14 @@ describe("ProcessingCancelledException", () => {
|
|
|
36
36
|
expect(error).toBeInstanceOf(UseSmileIDException);
|
|
37
37
|
expect(error).toBeInstanceOf(Error);
|
|
38
38
|
});
|
|
39
|
+
|
|
40
|
+
it("carries an underlying cause when one is supplied", () => {
|
|
41
|
+
const underlying = new Error("upload aborted");
|
|
42
|
+
const error = new ProcessingCancelledException({ cause: underlying });
|
|
43
|
+
expect(error.cause).toBe(underlying);
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
it("leaves cause unset when none is supplied", () => {
|
|
47
|
+
expect(new ProcessingCancelledException().cause).toBeUndefined();
|
|
48
|
+
});
|
|
39
49
|
});
|
|
@@ -27,16 +27,17 @@ export class ConsentDeniedException extends UseSmileIDGeneralException {
|
|
|
27
27
|
*
|
|
28
28
|
* Surfaced through `onResult.failure` so partners can distinguish a
|
|
29
29
|
* user-initiated cancellation from a submission error, mirroring the
|
|
30
|
-
* native SDKs' `ProcessingCancelledException`.
|
|
30
|
+
* native SDKs' `ProcessingCancelledException`. An optional `cause` carries a submission failure that preceded the exit.
|
|
31
31
|
*/
|
|
32
32
|
export class ProcessingCancelledException extends UseSmileIDGeneralException {
|
|
33
33
|
readonly errorCode = UseSmileIDErrorCode.General.OperationFailed;
|
|
34
34
|
|
|
35
|
-
constructor() {
|
|
35
|
+
constructor(args: { cause?: unknown } = {}) {
|
|
36
36
|
super({
|
|
37
37
|
message: "Processing was cancelled",
|
|
38
38
|
suggestedFix:
|
|
39
39
|
"The user exited the processing screen before submission completed.",
|
|
40
|
+
...(args.cause !== undefined ? { cause: args.cause } : {}),
|
|
40
41
|
});
|
|
41
42
|
}
|
|
42
43
|
}
|
|
@@ -43,6 +43,7 @@ export { MissingCaptureForPreviewException } from "./missing_capture_for_preview
|
|
|
43
43
|
export { DuplicateScreenTypeException } from "./duplicate_screen_type_exception";
|
|
44
44
|
|
|
45
45
|
// Capture-config validation (`capture { }` block).
|
|
46
|
+
export { AgentModeWithEnhancedLivenessException } from "./agent_mode_with_enhanced_liveness_exception";
|
|
46
47
|
export { InvalidSelfieCaptureConfigException } from "./invalid_selfie_capture_config_exception";
|
|
47
48
|
export { InvalidDocumentCaptureConfigException } from "./invalid_document_capture_config_exception";
|
|
48
49
|
export { InvalidMissingCaptureTypeException } from "./invalid_missing_capture_type_exception";
|
|
@@ -2,9 +2,7 @@ import { UseSmileIDBuilderException } from "./use_smile_id_builder_exception";
|
|
|
2
2
|
import { UseSmileIDErrorCode } from "./use_smile_id_error_code";
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
|
-
*
|
|
6
|
-
* never set — the orchestrator can't pick a submission path without
|
|
7
|
-
* it.
|
|
5
|
+
* `jobType` was never set, or was set to a value that is not one of the SDK's job types.
|
|
8
6
|
*/
|
|
9
7
|
export class MissingJobTypeException extends UseSmileIDBuilderException {
|
|
10
8
|
readonly errorCode = UseSmileIDErrorCode.Builder.MissingJobType;
|
|
@@ -12,7 +10,7 @@ export class MissingJobTypeException extends UseSmileIDBuilderException {
|
|
|
12
10
|
constructor() {
|
|
13
11
|
super({
|
|
14
12
|
message:
|
|
15
|
-
"jobType is not set — it must be configured explicitly in the network { config { } } block",
|
|
13
|
+
"jobType is not set to one of the SDK's job types — it must be configured explicitly in the network { config { } } block",
|
|
16
14
|
suggestedFix:
|
|
17
15
|
"Set config.jobType in the network { config { } } block, e.g. config.jobType = JobType.DocumentVerification",
|
|
18
16
|
});
|
|
@@ -24,6 +24,7 @@ export const UseSmileIDErrorCode = {
|
|
|
24
24
|
MissingScreenConfiguration: "BUILDER_MISSING_SCREEN_CONFIG",
|
|
25
25
|
DuplicateScreenType: "BUILDER_DUPLICATE_SCREEN",
|
|
26
26
|
InvalidSelfieCaptureConfig: "BUILDER_INVALID_SELFIE_CONFIG",
|
|
27
|
+
AgentModeWithEnhancedLiveness: "BUILDER_AGENT_MODE_WITH_ENHANCED_LIVENESS",
|
|
27
28
|
InvalidDocumentCaptureConfig: "BUILDER_INVALID_DOCUMENT_CONFIG",
|
|
28
29
|
MissingMLConfiguration: "BUILDER_MISSING_ML_CONFIG",
|
|
29
30
|
MissingNetworkConfiguration: "BUILDER_MISSING_NETWORK_CONFIG",
|
|
@@ -15,11 +15,11 @@ describe("DocumentType presets", () => {
|
|
|
15
15
|
});
|
|
16
16
|
});
|
|
17
17
|
|
|
18
|
-
it("Passport is a landscape,
|
|
18
|
+
it("Passport is a landscape, two-sided document", () => {
|
|
19
19
|
expect(DocumentType.Passport).toEqual({
|
|
20
20
|
kind: "passport",
|
|
21
21
|
displayName: "Passport",
|
|
22
|
-
hasBackSide:
|
|
22
|
+
hasBackSide: true,
|
|
23
23
|
orientation: "Landscape",
|
|
24
24
|
knownAspectRatio: 356 / 272,
|
|
25
25
|
});
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
|
2
|
+
|
|
3
|
+
import { FlowStep } from "../flow_step";
|
|
4
|
+
import { HEAD_TURN_DIRECTIONS } from "../head_turn_direction";
|
|
5
|
+
|
|
6
|
+
/** FlowStep + head-turn direction order is load-bearing (nav advances through it); pin it. */
|
|
7
|
+
describe("flow model constants", () => {
|
|
8
|
+
it("FlowStep lists the steps in forward-navigation order", () => {
|
|
9
|
+
expect(FlowStep).toEqual([
|
|
10
|
+
"instructions",
|
|
11
|
+
"consent",
|
|
12
|
+
"permission",
|
|
13
|
+
"capture",
|
|
14
|
+
"preview",
|
|
15
|
+
"processing",
|
|
16
|
+
]);
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
it("HEAD_TURN_DIRECTIONS enumerates the three challenge directions in order", () => {
|
|
20
|
+
expect(HEAD_TURN_DIRECTIONS).toEqual([
|
|
21
|
+
"look_left",
|
|
22
|
+
"look_right",
|
|
23
|
+
"look_up",
|
|
24
|
+
]);
|
|
25
|
+
});
|
|
26
|
+
});
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import type * as ScreenOrientation from "expo-screen-orientation";
|
|
2
|
+
import type { GlobalPrivacyControl } from "./global_privacy_control";
|
|
3
|
+
|
|
1
4
|
/**
|
|
2
5
|
* Global SDK configuration flags. Snapshot produced by
|
|
3
6
|
* `UseSmileIDConfigBuilder.build()` — every field is populated, with
|
|
@@ -33,4 +36,23 @@ export type ConfigOptions = {
|
|
|
33
36
|
* `docs/Architecture.md § Rollout`.
|
|
34
37
|
*/
|
|
35
38
|
readonly allowOfflineMode: boolean;
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Partner-declared consent posture (`global_privacy_control`).
|
|
42
|
+
* `GlobalPrivacyControl.OptOut` (the default) forces the opt-out consent
|
|
43
|
+
* layout universally; `OptIn` keeps the legacy regional mechanics.
|
|
44
|
+
*/
|
|
45
|
+
readonly globalPrivacyControl: GlobalPrivacyControl;
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Orientation lock the SDK applies when a capture screen leaves the screen.
|
|
49
|
+
* Defaults to `PORTRAIT_UP`, the posture most hosts pin at their root
|
|
50
|
+
* layout; multi-orientation hosts set `DEFAULT` so the flow releases the
|
|
51
|
+
* clamp instead of leaving the app portrait-only after verification.
|
|
52
|
+
*
|
|
53
|
+
* Optional so a hand-written `ConfigOptions` literal still compiles; the
|
|
54
|
+
* builder always populates it, and an absent value takes the same
|
|
55
|
+
* `PORTRAIT_UP` default at the capture screen.
|
|
56
|
+
*/
|
|
57
|
+
readonly exitOrientations?: ScreenOrientation.OrientationLock;
|
|
36
58
|
};
|
|
@@ -34,7 +34,7 @@ const SOUTH_AFRICA_GREEN_BOOK: DocumentType = Object.freeze({
|
|
|
34
34
|
const PASSPORT: DocumentType = Object.freeze({
|
|
35
35
|
kind: "passport",
|
|
36
36
|
displayName: "Passport",
|
|
37
|
-
hasBackSide:
|
|
37
|
+
hasBackSide: true,
|
|
38
38
|
orientation: "Landscape",
|
|
39
39
|
knownAspectRatio: 356 / 272,
|
|
40
40
|
});
|
|
@@ -51,7 +51,7 @@ export type GenericDocumentArgs = {
|
|
|
51
51
|
export const DocumentType = {
|
|
52
52
|
/** South Africa Green Book — booklet-style, single-side, portrait. */
|
|
53
53
|
SouthAfricaGreenBook: SOUTH_AFRICA_GREEN_BOOK,
|
|
54
|
-
/** Passport —
|
|
54
|
+
/** Passport — landscape data page followed by a back-side capture. */
|
|
55
55
|
Passport: PASSPORT,
|
|
56
56
|
/** Catch-all without a preset; defaults to a landscape, two-sided "Document". */
|
|
57
57
|
GenericDocument(args: GenericDocumentArgs = {}): DocumentType {
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Partner-declared Global Privacy Control posture for the consent screen
|
|
3
|
+
* (`global_privacy_control` on the wire).
|
|
4
|
+
*
|
|
5
|
+
* Native mobile platforms expose no OS-level equivalent of the web's GPC
|
|
6
|
+
* signal, so the SDK performs no runtime user-signal tracking: the partner
|
|
7
|
+
* declares the posture once at initialization
|
|
8
|
+
* (`b.config((c) => { c.globalPrivacyControl = ...; })`) and it governs
|
|
9
|
+
* every session.
|
|
10
|
+
*
|
|
11
|
+
* Const-object pattern (see `KameraEventType`-style types): enum ergonomics,
|
|
12
|
+
* string wire format.
|
|
13
|
+
*/
|
|
14
|
+
export const GlobalPrivacyControl = {
|
|
15
|
+
/**
|
|
16
|
+
* Default. Forces the opt-out consent layout universally: consent starts
|
|
17
|
+
* granted (pre-selected) for every session regardless of region — the
|
|
18
|
+
* user unticks to opt out. Regional detection is never consulted.
|
|
19
|
+
*/
|
|
20
|
+
OptOut: "opt-out",
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Legacy regional mechanics: consent starts granted outside the EU and
|
|
24
|
+
* starts ungranted (explicit opt-in required) when the device locale is
|
|
25
|
+
* an EU member state.
|
|
26
|
+
*/
|
|
27
|
+
OptIn: "opt-in",
|
|
28
|
+
} as const;
|
|
29
|
+
export type GlobalPrivacyControl =
|
|
30
|
+
(typeof GlobalPrivacyControl)[keyof typeof GlobalPrivacyControl];
|
|
31
|
+
|
|
32
|
+
/** Configuration key this setting is transported under. */
|
|
33
|
+
export const GLOBAL_PRIVACY_CONTROL_WIRE_KEY = "global_privacy_control";
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Parses a wire value ("opt-out" / "opt-in"); anything else falls back to
|
|
37
|
+
* the `OptOut` baseline default.
|
|
38
|
+
*/
|
|
39
|
+
export function globalPrivacyControlFromWire(
|
|
40
|
+
value: string | null | undefined,
|
|
41
|
+
): GlobalPrivacyControl {
|
|
42
|
+
return value === GlobalPrivacyControl.OptIn
|
|
43
|
+
? GlobalPrivacyControl.OptIn
|
|
44
|
+
: GlobalPrivacyControl.OptOut;
|
|
45
|
+
}
|
|
@@ -97,10 +97,10 @@ export type CacheConfig = {
|
|
|
97
97
|
};
|
|
98
98
|
|
|
99
99
|
/**
|
|
100
|
-
* Retry strategy.
|
|
100
|
+
* Retry strategy. `none` is the default.
|
|
101
|
+
* - `none`: one attempt, no retry — `maxAttempts` is forced to 1
|
|
101
102
|
* - `exponential`: `delay = min(initialDelay × multiplier^attempt, maxDelay)` plus `±jitter`
|
|
102
103
|
* - `fixed`: constant `fixedDelay` between attempts
|
|
103
|
-
* - `none`: no retry (`maxAttempts: 1`)
|
|
104
104
|
*/
|
|
105
105
|
export enum RetryStrategy {
|
|
106
106
|
exponential = "exponential",
|