@smileid/usesmileid 12.1.1 → 12.2.1-SNAPSHOT.44
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 +4 -2
- package/README.md +67 -23
- package/dist/camera/bounding_box_metering_region.d.ts +10 -0
- package/dist/camera/bounding_box_metering_region.js +1 -0
- package/dist/camera/document_image_pipeline.d.ts +10 -1
- package/dist/camera/document_image_pipeline.js +1 -1
- package/dist/camera/imported_document_folder.d.ts +15 -0
- package/dist/camera/imported_document_folder.js +1 -0
- package/dist/camera/kamera_config_factory.d.ts +11 -1
- package/dist/camera/kamera_config_factory.js +1 -1
- package/dist/camera/use_smile_id_frame_stream.js +1 -1
- package/dist/camera/use_smile_id_kamera_camera_system.d.ts +52 -2
- package/dist/camera/use_smile_id_kamera_camera_system.js +1 -1
- package/dist/core/exception/invalid_job_type_screen_config_exception.js +1 -1
- package/dist/core/exception/missing_partner_config_exception.d.ts +2 -0
- package/dist/core/exception/missing_partner_config_exception.js +1 -1
- package/dist/core/exception/unused_job_params_exception.js +1 -1
- package/dist/core/exception/use_smile_id_error_code.d.ts +1 -0
- package/dist/core/exception/use_smile_id_error_code.js +1 -1
- package/dist/core/exception/use_smile_id_network_exception.d.ts +12 -4
- package/dist/core/exception/use_smile_id_network_exception.js +1 -1
- package/dist/core/is_development_build.d.ts +6 -0
- package/dist/core/is_development_build.js +1 -0
- package/dist/core/models/config.d.ts +6 -0
- package/dist/core/models/document_type.d.ts +1 -1
- package/dist/core/models/job_type.d.ts +5 -0
- package/dist/core/models/job_type.js +1 -1
- package/dist/core/models/ml_config.d.ts +1 -1
- package/dist/core/models/network_config.d.ts +6 -4
- package/dist/core/models/params.d.ts +18 -0
- package/dist/core/models/params.js +1 -1
- package/dist/core/models/result.d.ts +11 -0
- package/dist/core/models/result.js +1 -1
- package/dist/core/perf/capture_perf_trace.d.ts +90 -0
- package/dist/core/perf/capture_perf_trace.js +1 -0
- package/dist/data/api/interceptors/logging_interceptor.js +1 -1
- package/dist/data/api/interceptors/smile_auth_interceptor.js +1 -1
- package/dist/data/api/request_capture.d.ts +16 -0
- package/dist/data/api/request_capture.js +1 -0
- package/dist/data/api/smile_id_api.d.ts +7 -13
- package/dist/data/api/smile_id_api.js +1 -1
- package/dist/data/compression/compressible_asset.d.ts +9 -1
- package/dist/data/compression/compressible_asset.js +1 -1
- package/dist/data/compression/payload_compression_runner.d.ts +3 -0
- package/dist/data/compression/payload_compression_runner.js +1 -1
- package/dist/data/compression/payload_compressor.js +1 -1
- package/dist/data/factory/networking_factory.d.ts +5 -1
- package/dist/data/factory/networking_factory.js +1 -1
- package/dist/data/model/captured_job.d.ts +49 -0
- package/dist/data/model/captured_job.js +1 -0
- package/dist/data/model/job_request.d.ts +21 -2
- package/dist/data/model/sealed_job_request.d.ts +15 -0
- package/dist/data/model/sealed_job_request.js +1 -0
- package/dist/data/model/token_payload.d.ts +17 -1
- package/dist/data/model/token_payload.js +1 -1
- package/dist/data/repository/use_smile_id_repository.d.ts +7 -0
- package/dist/data/repository/use_smile_id_repository_impl.d.ts +29 -2
- package/dist/data/repository/use_smile_id_repository_impl.js +1 -1
- package/dist/data/security/job_package_crypto.d.ts +41 -0
- package/dist/data/security/job_package_crypto.js +1 -0
- package/dist/data/security/job_package_sealer.d.ts +35 -0
- package/dist/data/security/job_package_sealer.js +1 -0
- package/dist/data/security/signing_crypto.d.ts +34 -0
- package/dist/data/security/signing_crypto.js +1 -1
- package/dist/data/util/retry_util.d.ts +9 -6
- package/dist/data/util/retry_util.js +1 -1
- package/dist/debug/capture_debug_geometry.d.ts +29 -0
- package/dist/debug/capture_debug_geometry.js +1 -0
- package/dist/debug/document_preview_debug_geometry.d.ts +36 -0
- package/dist/debug/document_preview_debug_geometry.js +1 -0
- package/dist/debug/preview_debug_drawing.d.ts +51 -0
- package/dist/debug/preview_debug_drawing.js +1 -0
- package/dist/debug/selfie_preview_debug_geometry.d.ts +55 -0
- package/dist/debug/selfie_preview_debug_geometry.js +1 -0
- package/dist/debug/use_smile_id_debug.d.ts +84 -0
- package/dist/debug/use_smile_id_debug.js +1 -0
- package/dist/debug/use_smile_id_debug_tap.d.ts +25 -0
- package/dist/debug/use_smile_id_debug_tap.js +1 -0
- package/dist/debug/use_smile_id_document_capture_debug_overlay.d.ts +56 -0
- package/dist/debug/use_smile_id_document_capture_debug_overlay.js +1 -0
- package/dist/debug/use_smile_id_document_preview_debug_overlay.d.ts +32 -0
- package/dist/debug/use_smile_id_document_preview_debug_overlay.js +1 -0
- package/dist/debug/use_smile_id_selfie_capture_debug_overlay.d.ts +27 -0
- package/dist/debug/use_smile_id_selfie_capture_debug_overlay.js +1 -0
- package/dist/debug/use_smile_id_selfie_preview_debug_overlay.d.ts +64 -0
- package/dist/debug/use_smile_id_selfie_preview_debug_overlay.js +1 -0
- package/dist/index.d.ts +12 -2
- package/dist/index.js +1 -1
- package/dist/l10n/strings_en.d.ts +5 -4
- package/dist/l10n/strings_en.js +2 -2
- package/dist/l10n/use_smile_id_localizations.d.ts +6 -7
- package/dist/l10n/use_smile_id_localizations.js +1 -1
- package/dist/metadata/document_image_origin.d.ts +1 -0
- package/dist/metadata/document_image_origin.js +1 -1
- package/dist/metadata/metadata_configuration_mappers.d.ts +3 -5
- package/dist/metadata/metadata_configuration_mappers.js +1 -1
- package/dist/metadata/use_smile_id_metadata_factory.d.ts +4 -4
- package/dist/metadata/use_smile_id_metadata_factory.js +1 -1
- package/dist/presentation/assets/si_dark_lighting_animation.json +1 -927
- package/dist/presentation/assets/si_device_orientation_animation.json +1 -850
- package/dist/presentation/assets/si_document_green_book_hero_animation.json +1 -4740
- package/dist/presentation/assets/si_document_hero_animation.json +1 -4870
- package/dist/presentation/assets/si_document_hero_back_animation.json +1 -2122
- package/dist/presentation/assets/si_document_passport_hero_animation.json +1 -14540
- package/dist/presentation/assets/si_document_visa_hero_animation.json +1 -0
- package/dist/presentation/assets/si_ess_all_directions_hero_animation.json +1 -5906
- package/dist/presentation/assets/si_ess_animation_all_directions.json +1 -5906
- package/dist/presentation/assets/si_selfie_hero_animation.json +1 -1468
- package/dist/presentation/assets/si_smile_to_capture_animation.json +1 -1412
- package/dist/presentation/components/helpers/captured_image_uri.d.ts +11 -0
- package/dist/presentation/components/helpers/captured_image_uri.js +1 -0
- package/dist/presentation/components/helpers/captured_oval_region.d.ts +40 -0
- package/dist/presentation/components/helpers/captured_oval_region.js +1 -0
- package/dist/presentation/components/helpers/document_interior_crop.d.ts +54 -0
- package/dist/presentation/components/helpers/document_interior_crop.js +1 -0
- package/dist/presentation/components/helpers/enhanced_smart_selfie_animation_frames.d.ts +35 -29
- package/dist/presentation/components/helpers/enhanced_smart_selfie_animation_frames.js +1 -1
- package/dist/presentation/components/helpers/selfie_interior_crop.d.ts +60 -0
- package/dist/presentation/components/helpers/selfie_interior_crop.js +1 -0
- package/dist/presentation/components/use_smile_id_capture_content.d.ts +12 -3
- package/dist/presentation/components/use_smile_id_capture_content.js +1 -1
- package/dist/presentation/components/use_smile_id_captured_document_image.d.ts +16 -0
- package/dist/presentation/components/use_smile_id_captured_document_image.js +1 -1
- package/dist/presentation/components/use_smile_id_captured_image_oval.d.ts +18 -4
- package/dist/presentation/components/use_smile_id_captured_image_oval.js +1 -1
- package/dist/presentation/components/use_smile_id_document_overlay.d.ts +12 -1
- package/dist/presentation/components/use_smile_id_document_overlay.js +1 -1
- package/dist/presentation/components/use_smile_id_document_shimmer.d.ts +10 -5
- package/dist/presentation/components/use_smile_id_document_shimmer.js +1 -1
- package/dist/presentation/components/use_smile_id_enhanced_smart_selfie_clip.d.ts +17 -7
- package/dist/presentation/components/use_smile_id_enhanced_smart_selfie_clip.js +1 -1
- package/dist/presentation/components/use_smile_id_enhanced_smart_selfie_direction_animation.d.ts +13 -14
- package/dist/presentation/components/use_smile_id_enhanced_smart_selfie_direction_animation.js +1 -1
- package/dist/presentation/components/use_smile_id_enhanced_smart_selfie_full_animation.js +1 -1
- package/dist/presentation/components/use_smile_id_face_oval_image.js +1 -1
- package/dist/presentation/flow/analytics/unsatisfied_reasons.d.ts +14 -0
- package/dist/presentation/flow/analytics/unsatisfied_reasons.js +1 -0
- package/dist/presentation/flow/analytics/use_smile_id_analytics_event.d.ts +12 -8
- package/dist/presentation/flow/analytics/use_smile_id_analytics_event.js +1 -1
- package/dist/presentation/flow/analytics/use_smile_id_analytics_event_kind.d.ts +98 -0
- package/dist/presentation/flow/analytics/use_smile_id_analytics_event_kind.js +1 -0
- package/dist/presentation/flow/config/flow_configuration_camera.d.ts +9 -0
- package/dist/presentation/flow/config/flow_configuration_camera.js +1 -0
- package/dist/presentation/flow/dsl/builder/config_builder.d.ts +6 -0
- package/dist/presentation/flow/dsl/builder/config_builder.js +1 -1
- package/dist/presentation/flow/dsl/builder/ml_builder.d.ts +1 -7
- package/dist/presentation/flow/dsl/builder/ml_builder.js +1 -1
- package/dist/presentation/flow/dsl/builder/screens_builder.d.ts +4 -2
- package/dist/presentation/flow/dsl/builder/screens_builder.js +1 -1
- package/dist/presentation/flow/dsl/use_smile_id_flow_builder.d.ts +17 -13
- package/dist/presentation/flow/dsl/use_smile_id_flow_builder.js +1 -1
- package/dist/presentation/flow/flow_navigation_manager.d.ts +72 -57
- package/dist/presentation/flow/flow_navigation_manager.js +1 -1
- package/dist/presentation/flow/flow_navigation_manager_analytics.d.ts +23 -0
- package/dist/presentation/flow/flow_navigation_manager_analytics.js +1 -0
- package/dist/presentation/flow/flow_navigation_manager_documents.d.ts +18 -0
- package/dist/presentation/flow/flow_navigation_manager_documents.js +1 -0
- package/dist/presentation/flow/flow_navigation_manager_job_request.d.ts +7 -0
- package/dist/presentation/flow/flow_navigation_manager_job_request.js +1 -0
- package/dist/presentation/flow/flow_navigation_manager_routing.d.ts +12 -0
- package/dist/presentation/flow/flow_navigation_manager_routing.js +1 -0
- package/dist/presentation/flow/flow_navigation_manager_submission.d.ts +17 -0
- package/dist/presentation/flow/flow_navigation_manager_submission.js +1 -0
- package/dist/presentation/flow/job_submission_state.d.ts +4 -0
- package/dist/presentation/flow/model/instructions_defaults.d.ts +1 -0
- package/dist/presentation/flow/model/instructions_defaults.js +1 -1
- package/dist/presentation/flow/screen/helpers/always_enabled_slot.d.ts +8 -0
- package/dist/presentation/flow/screen/helpers/always_enabled_slot.js +1 -0
- package/dist/presentation/flow/screen/helpers/face_session_config.d.ts +1 -1
- package/dist/presentation/flow/screen/helpers/failure_message.js +1 -1
- package/dist/presentation/flow/screen/orchestrated_capture_screen.js +1 -1
- package/dist/presentation/flow/screen/orchestrated_consent_screen.js +1 -1
- package/dist/presentation/flow/screen/orchestrated_instructions_screen.js +1 -1
- package/dist/presentation/flow/screen/orchestrated_preview_screen.js +1 -1
- package/dist/presentation/flow/screen/orchestrated_processing_screen.js +1 -1
- package/dist/presentation/flow/use_smile_id_flow.js +1 -1
- package/dist/presentation/flow/validation/flow_validator.d.ts +13 -12
- package/dist/presentation/flow/validation/flow_validator.js +1 -1
- package/dist/presentation/flow/validation/job_type_validator.d.ts +9 -1
- package/dist/presentation/flow/validation/job_type_validator.js +1 -1
- package/dist/presentation/screen/helpers/capture_screen_helpers.d.ts +0 -12
- package/dist/presentation/screen/helpers/capture_screen_helpers.js +1 -1
- package/dist/presentation/screen/helpers/capture_ui_state.d.ts +33 -6
- package/dist/presentation/screen/helpers/capture_ui_state.js +1 -1
- package/dist/presentation/screen/helpers/dropped_frames.d.ts +6 -0
- package/dist/presentation/screen/helpers/dropped_frames.js +1 -0
- package/dist/presentation/screen/helpers/ess_turn_haptics.d.ts +2 -0
- package/dist/presentation/screen/helpers/ess_turn_haptics.js +1 -1
- package/dist/presentation/screen/helpers/instructions_screen_helpers.d.ts +5 -1
- package/dist/presentation/screen/helpers/instructions_screen_helpers.js +1 -1
- package/dist/presentation/screen/helpers/use_capture_orientation_lock.d.ts +23 -1
- package/dist/presentation/screen/helpers/use_capture_orientation_lock.js +1 -1
- package/dist/presentation/screen/helpers/use_debounced_feedback_key.d.ts +1 -1
- package/dist/presentation/screen/helpers/use_debounced_feedback_key.js +1 -1
- package/dist/presentation/screen/use_smile_id_capture_screen.d.ts +9 -1
- package/dist/presentation/screen/use_smile_id_capture_screen.js +1 -1
- package/dist/presentation/screen/use_smile_id_consent_screen.js +1 -1
- package/dist/presentation/screen/use_smile_id_document_back_instructions.js +1 -1
- package/dist/presentation/screen/use_smile_id_document_preview_screen.d.ts +5 -0
- package/dist/presentation/screen/use_smile_id_document_preview_screen.js +1 -1
- package/dist/presentation/screen/use_smile_id_preview_screen.d.ts +3 -0
- package/dist/presentation/screen/use_smile_id_preview_screen.js +1 -1
- package/dist/presentation/screen/use_smile_id_processing_screen.d.ts +8 -0
- package/dist/presentation/screen/use_smile_id_processing_screen.js +1 -1
- package/dist/presentation/utils/locale_utils.d.ts +3 -6
- package/dist/presentation/utils/locale_utils.js +1 -1
- package/dist/testing/scenario_expectations.d.ts +7 -2
- package/dist/testing/scenario_expectations.js +1 -1
- package/dist/testing/scripted_scan_results.d.ts +2 -1
- package/dist/testing/scripted_scan_results.js +1 -1
- package/package.json +15 -15
package/CHANGELOG.md
CHANGED
|
@@ -1,15 +1,17 @@
|
|
|
1
1
|
Full release notes: [Smile ID docs](https://docs.usesmileid.com/developer-resources/sdks/mobile/release-notes/react-native-expo).
|
|
2
2
|
|
|
3
|
+
## 12.2.0
|
|
4
|
+
|
|
5
|
+
See the repository CHANGELOG for the 12.2.0 release notes.
|
|
6
|
+
|
|
3
7
|
## 12.1.1
|
|
4
8
|
|
|
5
9
|
See the repository CHANGELOG for the 12.1.1 release notes.
|
|
6
10
|
|
|
7
|
-
|
|
8
11
|
## 12.1.0
|
|
9
12
|
|
|
10
13
|
See the repository CHANGELOG for the 12.1.0 release notes.
|
|
11
14
|
|
|
12
|
-
|
|
13
15
|
## 12.0.2
|
|
14
16
|
|
|
15
17
|
See the repository CHANGELOG for the 12.0.2 release notes.
|
package/README.md
CHANGED
|
@@ -32,7 +32,7 @@ Sizes are measured on every push to `main` and updated automatically by CI.
|
|
|
32
32
|
- Xcode (latest stable) — iOS 16.4 deployment target (set by Expo SDK 56's modules; the Smile ID iOS SDK itself supports iOS 15)
|
|
33
33
|
- Android Gradle Plugin 8.11.1+ — `compileSdk` 36 or newer (React Native's default; nothing to set) and `minSdk` 24, matching the native Smile ID SDK and the kamera engine. The ML Kit config plugins set the Kotlin and KSP versions the AARs were compiled with. The 12.0.0–12.0.2 AARs required compileSdk 37 and `minSdk` 26 instead; on those releases, install platform 37 before Gradle runs (on EAS, an `eas-build-pre-install` script: `yes | sdkmanager --licenses >/dev/null; sdkmanager "platforms;android-37.0"`).
|
|
34
34
|
|
|
35
|
-
`12.
|
|
35
|
+
`12.2.0` is built and verified against Expo SDK 57 and React Native 0.86. The floors above are the supported minimum and keep working.
|
|
36
36
|
|
|
37
37
|
## Installation
|
|
38
38
|
|
|
@@ -143,7 +143,7 @@ export default function VerificationScreen() {
|
|
|
143
143
|
|
|
144
144
|
## Full Builder Reference
|
|
145
145
|
|
|
146
|
-
`useSmileIDBuilder` takes a callback that receives a mutable builder. Top-level mutable properties (`consentInformation`, `enhancedKYCParams`, `biometricKYCParams`, `documentVerificationParams`, `enhancedDocumentVerificationParams`, `userDetails`, `localizations`, `onResult`, `onAnalyticsEvent`) are property-assigned. Nested blocks (`config`, `theme`, `network`, `ml`, `screens`) take closures.
|
|
146
|
+
`useSmileIDBuilder` takes a callback that receives a mutable builder. Top-level mutable properties (`consentInformation`, `enhancedKYCParams`, `biometricKYCParams`, `documentVerificationParams`, `enhancedDocumentVerificationParams`, `residencyDocumentVerificationParams`, `userDetails`, `localizations`, `onResult`, `onAnalyticsEvent`) are property-assigned. Nested blocks (`config`, `theme`, `network`, `ml`, `screens`) take closures.
|
|
147
147
|
|
|
148
148
|
The server issues `userId` and `jobId` and returns them in the submission response — partners receive both via `onResult`. Don't construct them client-side.
|
|
149
149
|
|
|
@@ -153,6 +153,7 @@ The server issues `userId` and `jobId` and returns them in the submission respon
|
|
|
153
153
|
b.config((c) => {
|
|
154
154
|
c.enableDebugMode = false;
|
|
155
155
|
c.allowOfflineMode = false;
|
|
156
|
+
c.skipApiSubmission = false;
|
|
156
157
|
c.enableCrashReporting = true;
|
|
157
158
|
c.showAttribution = true;
|
|
158
159
|
});
|
|
@@ -162,6 +163,7 @@ b.config((c) => {
|
|
|
162
163
|
| ---------------------- | --------- | ------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
163
164
|
| `enableDebugMode` | `boolean` | `false` | Shows a validation error screen on build failure |
|
|
164
165
|
| `allowOfflineMode` | `boolean` | `false` | Allows the flow to run without a network connection |
|
|
166
|
+
| `skipApiSubmission` | `boolean` | `false` | Captures the job and hands it back as `{ status: "captured", job }` instead of submitting it. The files stay on disk for you to forward and delete |
|
|
165
167
|
| `enableCrashReporting` | `boolean` | `true` | Enables Sentry crash reporting for the SDK. Set to `false` if your app runs its own Sentry |
|
|
166
168
|
| `showAttribution` | `boolean` | `true` | Shows the "Powered by Smile ID" mark on every screen that carries it. Set to `false` to hide it across the whole journey. Document capture never shows the mark |
|
|
167
169
|
|
|
@@ -246,7 +248,7 @@ b.network((n) => {
|
|
|
246
248
|
c.onTokenExpired = async (previous) => fetchFreshToken();
|
|
247
249
|
c.partnerConfig((p) => {
|
|
248
250
|
p.partnerId = "your-partner-id";
|
|
249
|
-
p.callbackUrl = "https://
|
|
251
|
+
p.callbackUrl = "https://your-registered-domain/webhook";
|
|
250
252
|
p.useSandbox = false;
|
|
251
253
|
});
|
|
252
254
|
c.logging((l) => {
|
|
@@ -268,7 +270,7 @@ b.network((n) => {
|
|
|
268
270
|
i.add(i.gzip());
|
|
269
271
|
i.add(
|
|
270
272
|
i.logging((l) => {
|
|
271
|
-
l.level = LogLevel.body;
|
|
273
|
+
l.level = LogLevel.body; // bodies in a development build only
|
|
272
274
|
}),
|
|
273
275
|
);
|
|
274
276
|
i.add(myCustomInterceptor); // partner-supplied
|
|
@@ -286,12 +288,12 @@ b.network((n) => {
|
|
|
286
288
|
|
|
287
289
|
#### `partnerConfig` block
|
|
288
290
|
|
|
289
|
-
| Property | Type | Default | Description
|
|
290
|
-
| --------------- | ------------------------- | ----------- |
|
|
291
|
-
| `partnerId` | `string` | `""` | Your Smile ID partner ID
|
|
292
|
-
| `callbackUrl` | `string` | `""` | Webhook URL for job results
|
|
293
|
-
| `useSandbox` | `boolean` | `false` | Route requests to the sandbox environment
|
|
294
|
-
| `partnerParams` | `Record<string, string>?` | `undefined` | Optional partner-defined key/value pairs forwarded as the `partner_params` JSON multipart part on Enhanced/Biometric KYC submissions
|
|
291
|
+
| Property | Type | Default | Description |
|
|
292
|
+
| --------------- | ------------------------- | ----------- | --------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
293
|
+
| `partnerId` | `string` | `""` | Your Smile ID partner ID |
|
|
294
|
+
| `callbackUrl` | `string` | `""` | Webhook URL for job results. Sent on every product when non-empty; blank omits it and the job uses the account's default for that environment |
|
|
295
|
+
| `useSandbox` | `boolean` | `false` | Route requests to the sandbox environment |
|
|
296
|
+
| `partnerParams` | `Record<string, string>?` | `undefined` | Optional partner-defined key/value pairs forwarded as the `partner_params` JSON multipart part on Enhanced/Biometric KYC submissions |
|
|
295
297
|
|
|
296
298
|
#### `logging` block
|
|
297
299
|
|
|
@@ -458,10 +460,10 @@ Calling `useFlowNavigation()` outside `<UseSmileIDBuilder>` throws — the misus
|
|
|
458
460
|
|
|
459
461
|
## Top-level builder callbacks
|
|
460
462
|
|
|
461
|
-
| Property | Type | Description
|
|
462
|
-
| ------------------ | ----------------------------------------------------------- |
|
|
463
|
-
| `onResult` | `(result: UseSmileIDResult<JobSubmissionResponse>) => void` | Called once when the flow finishes (success or
|
|
464
|
-
| `onAnalyticsEvent` | `((event: UseSmileIDAnalyticsEvent) => void) \| undefined` | Optional. Called for each analytics event during the flow
|
|
463
|
+
| Property | Type | Description |
|
|
464
|
+
| ------------------ | ----------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------ |
|
|
465
|
+
| `onResult` | `(result: UseSmileIDResult<JobSubmissionResponse>) => void` | Called once when the flow finishes (success, failure, cancelled, or captured when `skipApiSubmission` is on) |
|
|
466
|
+
| `onAnalyticsEvent` | `((event: UseSmileIDAnalyticsEvent) => void) \| undefined` | Optional. Called for each analytics event during the flow |
|
|
465
467
|
|
|
466
468
|
---
|
|
467
469
|
|
|
@@ -469,12 +471,13 @@ Calling `useFlowNavigation()` outside `<UseSmileIDBuilder>` throws — the misus
|
|
|
469
471
|
|
|
470
472
|
Each job type that needs identity fields reads them from a top-level builder property. The shared `user_details` part (`b.userDetails`) is required by every KYC and document job; `country` is the ISO 3166-1 alpha-2 code.
|
|
471
473
|
|
|
472
|
-
| Job type
|
|
473
|
-
|
|
|
474
|
-
| `JobType.enhancedKyc`
|
|
475
|
-
| `JobType.biometricKyc`
|
|
476
|
-
| `JobType.documentVerification`
|
|
477
|
-
| `JobType.enhancedDocumentVerification`
|
|
474
|
+
| Job type | Builder property | Required fields | Notes |
|
|
475
|
+
| --------------------------------------- | --------------------------------------- | ------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
476
|
+
| `JobType.enhancedKyc` | `b.enhancedKYCParams` | `idType`, `idNumber`, `country` | Optional `bankCode`, `mobileOperator` |
|
|
477
|
+
| `JobType.biometricKyc` | `b.biometricKYCParams` | `idType`, `idNumber`, `country` | `useEnrolledImage` toggles the enrolled-image path |
|
|
478
|
+
| `JobType.documentVerification` | `b.documentVerificationParams` | `country` | `idType` **optional** — omit it to let the backend classify the document |
|
|
479
|
+
| `JobType.enhancedDocumentVerification` | `b.enhancedDocumentVerificationParams` | `country`, `idType` | `idType` **required** — drives the ID-authority cross-check |
|
|
480
|
+
| `JobType.residencyDocumentVerification` | `b.residencyDocumentVerificationParams` | `country`, `idType` | `idType` must be `"PASSPORT"` (exported as `RESIDENCY_ID_TYPE`); passport data page plus a mandatory visa page from one document capture step; the step must use `DocumentType.Passport`, and `allowSkipBack` is rejected |
|
|
478
481
|
|
|
479
482
|
```ts
|
|
480
483
|
// Document Verification — idType optional
|
|
@@ -492,8 +495,18 @@ b.userDetails = {
|
|
|
492
495
|
lastName: "Doe",
|
|
493
496
|
phoneNumber: "+254700000000",
|
|
494
497
|
};
|
|
498
|
+
|
|
499
|
+
// Residency Document Verification — passport data page, then a mandatory visa page
|
|
500
|
+
b.residencyDocumentVerificationParams = { country: "AE", idType: "PASSPORT" };
|
|
501
|
+
b.userDetails = {
|
|
502
|
+
givenNames: "Jane",
|
|
503
|
+
lastName: "Doe",
|
|
504
|
+
email: "jane@example.com",
|
|
505
|
+
};
|
|
495
506
|
```
|
|
496
507
|
|
|
508
|
+
`DocumentSide` (exported from `@smileid/usesmileid`) gains `Visa` (`"visa"`) for the residency visa page, so an exhaustive `switch` over it needs the new case.
|
|
509
|
+
|
|
497
510
|
`user_details` requires non-blank `givenNames` and `lastName` plus at least one of `email` / `phoneNumber`. Pre-flight any payload with `b.validateDocumentVerificationParams(...)`, `b.validateEnhancedDocumentVerificationParams(...)`, or `b.validateUserDetails(...)` before assigning.
|
|
498
511
|
|
|
499
512
|
---
|
|
@@ -511,13 +524,44 @@ b.onResult = (result) => {
|
|
|
511
524
|
case "failure":
|
|
512
525
|
console.error("flow failed:", result.error);
|
|
513
526
|
break;
|
|
527
|
+
case "cancelled":
|
|
528
|
+
console.log("user exited before finishing");
|
|
529
|
+
break;
|
|
530
|
+
case "captured":
|
|
531
|
+
console.log(
|
|
532
|
+
`captured ${result.job.jobType}; forward ${result.job.sessionDirectory}`,
|
|
533
|
+
);
|
|
534
|
+
break;
|
|
514
535
|
}
|
|
515
536
|
};
|
|
516
537
|
```
|
|
517
538
|
|
|
518
539
|
The success branch carries a `JobSubmissionResponse` with `jobId`, `userId`, `status`, `message`, and an optional `createdAt`. Partner-supplied inputs (captured frames, identity fields, consent) are not echoed back — keep references at the call site if you need them after the flow.
|
|
519
540
|
|
|
520
|
-
`UseSmileIDResult<T>` is a discriminated union — `result.status` narrows it, no `try` / `catch` needed.
|
|
541
|
+
`UseSmileIDResult<T>` is a discriminated union — `result.status` narrows it, no `try` / `catch` needed. The statuses are `"success"`, `"failure"`, `"cancelled"` (the user left before finishing — nothing was submitted) and `"captured"`, delivered only when `c.skipApiSubmission = true`.
|
|
542
|
+
|
|
543
|
+
A `"captured"` result carries a `CapturedJob`:
|
|
544
|
+
|
|
545
|
+
| Field | Type | Description |
|
|
546
|
+
| ------------------------------- | ---------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
547
|
+
| `jobType` | `JobType` | The configured job type |
|
|
548
|
+
| `sessionId` | `string` | The flow's session id, also on every analytics event |
|
|
549
|
+
| `sessionDirectory` | `string \| undefined` | The session folder the SDK kept for this job. In this mode the SDK deletes neither it nor the files, so once you have forwarded the job, delete every file listed here, then this folder and everything left in it. Absent when the files don't share one of the SDK's session folders (a document job's selfie and document come from separate capture sessions), or the job captured no files (Enhanced KYC) |
|
|
550
|
+
| `selfieImage` | `string \| undefined` | Selfie file URI for selfie-bearing jobs |
|
|
551
|
+
| `livenessImages` | `readonly string[]` | Liveness frame URIs for selfie-bearing jobs |
|
|
552
|
+
| `frontDocument`, `backDocument` | `string \| undefined` | Document side URIs for document jobs |
|
|
553
|
+
| `visaDocument` | `string \| undefined` | The visa page URI, for Residency Document Verification |
|
|
554
|
+
| `headers` | `Readonly<Record<string, string>>` | `smileid-token`, `smileid-source-sdk` and `smileid-source-sdk-version`, to send as request headers |
|
|
555
|
+
| `encryptedPackage` | `string` | The rest of the request, sealed for Smile ID; send it as the `encrypted_package` form field |
|
|
556
|
+
| `packageNonce`, `packageTag` | `string` | The package's nonce and tag; send them as the `package_nonce` and `package_tag` form fields |
|
|
557
|
+
|
|
558
|
+
To forward the job, send the job type's `/v3` request with `headers`, the images as their usual form parts, and the three package fields. The package holds everything else the SDK would have sent (the consent record, the metadata and the request signature), encrypted with AES-256-GCM for Smile ID. Forward it as is: the server rejects a package that was changed. Forward the image files byte-for-byte too: they carry an integrity seal that re-encoding invalidates. A document imported from the gallery or taken with the manual shutter is kept in the app's cache, which the OS may clear under storage pressure, so forward such a job promptly.
|
|
559
|
+
|
|
560
|
+
Send each file under the form part the SDK would have used: `selfieImage` as `selfie_image`, `livenessImages` as `liveness_images` in the list's order, `frontDocument` as `document`, `backDocument` as `document_back` and `visaDocument` as `visa`. The request signature in the package covers the images by part name and order, so the server rejects a job sent any other way. Forward the job soon after the flow ends: the package carries the access token and the request timestamp from the capture, which the server checks and which can't be refreshed without capturing again.
|
|
561
|
+
|
|
562
|
+
On iOS the system can move the app's data container between launches, for example across an app update, so don't save these absolute URIs. To forward a job in a later launch, save each path relative to the container and rebuild it then.
|
|
563
|
+
|
|
564
|
+
The processing screen keeps its spinner after the hand-over, because nothing was submitted, so unmount the flow in `onResult`, as for every other result.
|
|
521
565
|
|
|
522
566
|
### Forwarding failures to a crash reporter
|
|
523
567
|
|
|
@@ -576,7 +620,7 @@ Every event automatically includes `session_id` and `timestamp` (epoch milliseco
|
|
|
576
620
|
| `screen_viewed` | Each screen becomes active | `screen_name` |
|
|
577
621
|
| `consent_captured` | User grants consent | `decision: "granted"` |
|
|
578
622
|
| `selfie_captured` | Selfie + liveness captured | `liveness_image_count` |
|
|
579
|
-
| `document_captured` | Document image captured | `document_side: "front"` or `"
|
|
623
|
+
| `document_captured` | Document image captured | `document_side: "front"`, `"back"` or `"visa"`, one event per image |
|
|
580
624
|
| `retake_requested` | User navigates back to redo a step | — |
|
|
581
625
|
| `job_submitted` | API submission begins | `job_type`, `attempt` |
|
|
582
626
|
| `flow_completed` | Flow finishes | `result: "success"` or `"failure"`, `job_id` (success), `error_message` (failure) |
|
|
@@ -690,7 +734,7 @@ export function DocumentVerificationScreen({
|
|
|
690
734
|
c.token = "your-v3-token";
|
|
691
735
|
c.partnerConfig((p) => {
|
|
692
736
|
p.partnerId = "your-partner-id";
|
|
693
|
-
p.callbackUrl = "https://
|
|
737
|
+
p.callbackUrl = "https://your-registered-domain/webhook";
|
|
694
738
|
p.useSandbox = true;
|
|
695
739
|
});
|
|
696
740
|
c.logging((l) => {
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { KameraRegion } from "@smileid/kamera";
|
|
2
|
+
import type { BoundingBox } from "@smileid/usesmileid_bridge";
|
|
3
|
+
/**
|
|
4
|
+
* `box` as the region kamera meters exposure on, in the frame as displayed: flipped first when
|
|
5
|
+
* `flipped`, because the detector saw the unmirrored frame, then clamped to the frame. Null when
|
|
6
|
+
* none of it is inside.
|
|
7
|
+
*/
|
|
8
|
+
export declare function meteringRegion(box: Pick<BoundingBox, "left" | "top" | "width" | "height">, flipped: boolean): KameraRegion | null;
|
|
9
|
+
/** The largest of `faces` by area, or null when there are none. */
|
|
10
|
+
export declare function largestFace<T extends Pick<BoundingBox, "width" | "height">>(faces: readonly T[]): T | null;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";export function meteringRegion(t,n){const e=n?1-t.left-t.width:t.left,h=i(e),r=i(t.top),c=i(e+t.width),l=i(t.top+t.height);return c<=h||l<=r?null:{x:h,y:r,width:c-h,height:l-r}}export function largestFace(t){let n=null;for(const e of t)(n===null||e.width*e.height>n.width*n.height)&&(n=e);return n}function i(t){return Math.min(1,Math.max(0,t))}
|
|
@@ -1,6 +1,15 @@
|
|
|
1
1
|
import { DocumentSide } from "@smileid/usesmileid_bridge";
|
|
2
2
|
export { computeDocumentResizeTarget } from "./document_resize_target";
|
|
3
|
-
/**
|
|
3
|
+
/**
|
|
4
|
+
* Imported document image pipeline — brings a manual-shutter still or gallery
|
|
5
|
+
* image onto the SAME byte policy as the native auto-capture artifact: longest
|
|
6
|
+
* edge downscaled to {@link CameraDefaults.documentMaxDimension} at
|
|
7
|
+
* {@link CameraDefaults.documentJpegQuality}, written under the canonical
|
|
8
|
+
* per-side filename. The Smile EXIF `UserComment` tag is stamped downstream by
|
|
9
|
+
* `SmileExifTagger.finalize`, so every upload is byte-policy-identical
|
|
10
|
+
* regardless of capture path.
|
|
11
|
+
*/
|
|
12
|
+
/** Canonical per-image artifact basename, matching the auto-capture naming. */
|
|
4
13
|
export declare function documentArtifactFileName(side: DocumentSide): string;
|
|
5
14
|
/** Source image for an imported document capture (manual shutter or gallery). */
|
|
6
15
|
export type ImportedDocumentSource = {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";import{
|
|
1
|
+
"use strict";import{File as i}from"expo-file-system";import{ImageManipulator as m,SaveFormat as s}from"expo-image-manipulator";import{DocumentSide as o,UseSmileIDCrashReporting as u}from"@smileid/usesmileid_bridge";import{CameraDefaults as a}from"./camera_defaults";import{computeDocumentResizeTarget as d}from"./document_resize_target";import{newImportedDocumentFolder as p}from"./imported_document_folder";export{computeDocumentResizeTarget}from"./document_resize_target";export function documentArtifactFileName(t){switch(t){case o.Back:return"document_back.jpg";case o.Visa:return"document_visa.jpg";default:return"document_front.jpg"}}export async function resampleImportedDocument(t,n){const r=t.width!==void 0&&t.height!==void 0?d(t.width,t.height,a.documentMaxDimension):null,e=m.manipulate(t.uri);r&&e.resize(r);const c=await(await e.renderAsync()).saveAsync({compress:a.documentJpegQuality,format:s.JPEG});return f(c.uri,n)}function f(t,n){const r=p();try{r.exists||r.create({intermediates:!0});const e=new i(r,documentArtifactFileName(n));return e.exists&&e.delete(),new i(t).move(e),e.uri}catch(e){u.captureException(e instanceof Error?e:new Error(String(e)));try{r.exists&&r.delete()}catch{}return t}}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { Directory } from "expo-file-system";
|
|
2
|
+
/** Subdirectory under the cache directory holding imported document artifacts. */
|
|
3
|
+
export declare const IMPORT_SUBDIRECTORY = "usesmileid_documents";
|
|
4
|
+
/**
|
|
5
|
+
* A new `<cache>/usesmileid_documents/<id>/` folder for one import. Each import
|
|
6
|
+
* gets its own: a skip-submission hand-over gives the partner the path to
|
|
7
|
+
* forward later, so a later flow must never overwrite or delete it.
|
|
8
|
+
*/
|
|
9
|
+
export declare function newImportedDocumentFolder(): Directory;
|
|
10
|
+
/**
|
|
11
|
+
* Delete an imported document together with the folder it was written into. A
|
|
12
|
+
* no-op for any other file, such as a camera capture, so a caller can pass
|
|
13
|
+
* every document path it drops.
|
|
14
|
+
*/
|
|
15
|
+
export declare function deleteImportedDocument(uri: string): void;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";import{Directory as r,File as c,Paths as u}from"expo-file-system";import{generateSessionId as s}from"../metadata/use_smile_id_metadata_factory";export const IMPORT_SUBDIRECTORY="usesmileid_documents";export function newImportedDocumentFolder(){return new r(o(),s())}function o(){return new r(u.cache,IMPORT_SUBDIRECTORY)}function n(e){return e.replace(/\/+$/,"")}export function deleteImportedDocument(e){try{const t=new c(e).parentDirectory,i=n(o().uri);if(n(t.parentDirectory.uri)!==i)return;t.exists&&t.delete()}catch{}}
|
|
@@ -1,7 +1,17 @@
|
|
|
1
1
|
import type { KameraConfig, Lens } from "@smileid/kamera";
|
|
2
2
|
import { CaptureType } from "../core/models/ml_config";
|
|
3
3
|
import { CameraLens } from "./camera_lens";
|
|
4
|
-
/**
|
|
4
|
+
/**
|
|
5
|
+
* The selfie's analysis interval: 30 frames a second, which its 0.2 s
|
|
6
|
+
* reference window and the settling counted inside each 350 ms interval assume.
|
|
7
|
+
*/
|
|
8
|
+
export declare const SELFIE_ANALYSIS_INTERVAL_MS = 33;
|
|
9
|
+
/**
|
|
10
|
+
* Maps the SDK's capture inputs onto a kamera `KameraConfig` via the tuned kamera presets. A selfie
|
|
11
|
+
* analyses every {@link SELFIE_ANALYSIS_INTERVAL_MS} and asks for each frame's device motion (the
|
|
12
|
+
* shake gate), as the native screens do; on iOS it also asks for kamera's face tracking (ARKit on a
|
|
13
|
+
* TrueDepth front camera, whose tracked face the selfie reads).
|
|
14
|
+
*/
|
|
5
15
|
export declare const KameraConfigFactory: {
|
|
6
16
|
readonly create: (captureType: CaptureType, lens: CameraLens) => KameraConfig;
|
|
7
17
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";import{KameraDefaults as
|
|
1
|
+
"use strict";import{Platform as n}from"react-native";import{KameraDefaults as o}from"@smileid/kamera";import{CaptureType as m}from"../core/models/ml_config";import{CameraLens as i}from"./camera_lens";export const SELFIE_ANALYSIS_INTERVAL_MS=33,KameraConfigFactory={create(e,a){const r=toKameraLens(a);if(e===m.document)return o.document(r);const t=o.selfie(r);return{...t,analysis:{...t.analysis,minIntervalMs:SELFIE_ANALYSIS_INTERVAL_MS,deviceMotion:!0,...n.OS==="ios"?{faceTracking:!0}:{}}}}};export function toKameraLens(e){return e===i.back?"back":"front"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";import{useCallback as
|
|
1
|
+
"use strict";import{useCallback as y,useEffect as l,useMemo as E,useRef as a}from"react";import{documentScanResultSchema as S,faceScanResultSchema as h,FrameProcessingException as B}from"@smileid/usesmileid_bridge";import{isDevelopmentBuild as p}from"../core/is_development_build";import{UseSmileIDDebugTap as R}from"../debug/use_smile_id_debug_tap";export function useSmileIDFrameStream(e,r,o){const i=a(e),s=a(r),u=a(o?.onError),c=a(!1),f=a(!0);l(()=>{i.current=e},[e]),l(()=>{s.current=r},[r]),l(()=>{u.current=o?.onError},[o?.onError]),l(()=>(f.current=!0,()=>{f.current=!1}),[]);const n=y(t=>{const m=u.current;dispatchFrameResult({raw:t,analyzer:i.current,isBusy:()=>c.current,setBusy:d=>{c.current=d},isMounted:()=>f.current,onResult:s.current,...m!==void 0?{onError:m}:{}})},[]);return E(()=>({onFrameResult:n}),[n])}function D(e){if(e===null||typeof e!="object")return null;const r=e.error;return typeof r=="string"?r:null}const _=new Set(["no_frame","session_not_configured"]);export function dispatchFrameResult(e){const{raw:r,analyzer:o,isBusy:i,setBusy:s,isMounted:u,onResult:c,onError:f}=e;if(o&&!i()){s(!0);try{const n=D(r);if(n!==null){if(_.has(n))return;throw new B({reason:n})}if(o.kind==="face"){const t=h.parse(r);if(!u())return;c(t),p()&&R.analyzedFace(t.output)}else{const t=S.parse(r);if(!u())return;c(t),p()&&R.analyzedDocument(t.output)}}catch(n){if(!u())return;f?.(n)}finally{s(!1)}}}
|
|
@@ -1,11 +1,23 @@
|
|
|
1
1
|
import type { KameraCapabilities, KameraCaptureResult, KameraEvent } from "@smileid/kamera";
|
|
2
2
|
import { KameraSession } from "@smileid/kamera";
|
|
3
|
+
import { type BoundingBox, type DocumentGuide } from "@smileid/usesmileid_bridge";
|
|
3
4
|
import { CameraLens } from "./camera_lens";
|
|
4
5
|
import type { CameraConfiguration, CameraSystemState } from "./camera_configuration";
|
|
5
6
|
import type { FocusPoint, FocusState } from "./focus_state";
|
|
6
7
|
type Listener = (state: CameraSystemState, focus: FocusState) => void;
|
|
7
|
-
/**
|
|
8
|
-
|
|
8
|
+
/**
|
|
9
|
+
* The kamera session surface this system drives; structural so tests can inject an in-memory fake.
|
|
10
|
+
* `setMeteringRegion` is optional so a session built against the earlier surface still fits; without
|
|
11
|
+
* it the selfie meters the whole frame.
|
|
12
|
+
*/
|
|
13
|
+
export type KameraSessionLike = Pick<KameraSession, "start" | "stop" | "capture" | "setZoomRatio" | "setTorch" | "tapToFocus" | "setExposureCompensation" | "capabilities" | "release" | "addEventListener"> & Partial<Pick<KameraSession, "setMeteringRegion" | "setDocumentGuide" | "setMetricsEnabled">>;
|
|
14
|
+
/**
|
|
15
|
+
* Turns kamera's perf metrics on or off from the next camera start; they arrive as `metric`
|
|
16
|
+
* events. Internal: the capture screen calls it for the perf trace.
|
|
17
|
+
*/
|
|
18
|
+
export declare function setKameraMetricsWanted(enabled: boolean): void;
|
|
19
|
+
/** Test seam: forgets what was sent to kamera. */
|
|
20
|
+
export declare function resetKameraMetricsForTesting(): void;
|
|
9
21
|
/**
|
|
10
22
|
* Kamera-backed orchestrator: drives the native session and republishes its state via `subscribe()`.
|
|
11
23
|
* Pixels never cross the bridge — frame analysis and still capture run in the native cores.
|
|
@@ -28,6 +40,12 @@ export declare class UseSmileIDKameraCameraSystem {
|
|
|
28
40
|
get focusState(): FocusState;
|
|
29
41
|
/** Device/session capabilities, available once running. */
|
|
30
42
|
get capabilities(): KameraCapabilities | null;
|
|
43
|
+
/**
|
|
44
|
+
* The upright preview's width over its height on a portrait screen: the configured session's
|
|
45
|
+
* preview ratio with its short side across. kamera binds the analysis stream to the same ratio,
|
|
46
|
+
* so it is also the analysed frame's.
|
|
47
|
+
*/
|
|
48
|
+
get uprightPreviewAspect(): number;
|
|
31
49
|
/**
|
|
32
50
|
* The active session, for `UseSmileIDKameraPreview` only — drive it through this class's API.
|
|
33
51
|
* Null until `start()` succeeds.
|
|
@@ -45,6 +63,33 @@ export declare class UseSmileIDKameraCameraSystem {
|
|
|
45
63
|
capture(): Promise<KameraCaptureResult>;
|
|
46
64
|
/** Sets zoom, clamped to the session's capability range. */
|
|
47
65
|
setZoomRatio(ratio: number): Promise<void>;
|
|
66
|
+
/** The guide last asked for: what the camera should hold. */
|
|
67
|
+
private _documentGuide;
|
|
68
|
+
/** Whether the current session confirmed `_documentGuide`. */
|
|
69
|
+
private _documentGuideApplied;
|
|
70
|
+
/** The session a guide is being sent to, so only one send is in flight. */
|
|
71
|
+
private _documentGuideSendingTo;
|
|
72
|
+
private _documentGuideFailureReported;
|
|
73
|
+
/**
|
|
74
|
+
* Sets what the document guide frames, so the camera zooms only as far as
|
|
75
|
+
* the document filling the guide needs to stay in focus. Null clears it and
|
|
76
|
+
* leaves the camera's default close-focus floor.
|
|
77
|
+
*
|
|
78
|
+
* Called on every frame: a repeat sends nothing, and only one guide is in
|
|
79
|
+
* flight at a time, the latest one asked for following it. A guide set
|
|
80
|
+
* before the camera starts reaches it once it does. A guide the camera
|
|
81
|
+
* refuses is sent again on the next call; the first refusal is reported to
|
|
82
|
+
* crash reporting. Never rejects.
|
|
83
|
+
*/
|
|
84
|
+
setDocumentGuide(guide: DocumentGuide | null): Promise<void>;
|
|
85
|
+
/**
|
|
86
|
+
* Sends the guide asked for to the current session until it holds the
|
|
87
|
+
* latest one, one send at a time; stops at a refusal, which the next call
|
|
88
|
+
* retries, or when the session changes, whose start sends the guide itself.
|
|
89
|
+
*/
|
|
90
|
+
private _applyDocumentGuide;
|
|
91
|
+
/** Sends `guide` to `session`; false when the session refuses it. */
|
|
92
|
+
private _sendDocumentGuide;
|
|
48
93
|
/** Toggles the torch; a no-op without a flash unit. */
|
|
49
94
|
setTorch(enabled: boolean): Promise<void>;
|
|
50
95
|
/**
|
|
@@ -52,6 +97,11 @@ export declare class UseSmileIDKameraCameraSystem {
|
|
|
52
97
|
* Drives the reticle running → success → unspecified on the standard cadence.
|
|
53
98
|
*/
|
|
54
99
|
tapToFocus(point: FocusPoint): Promise<void>;
|
|
100
|
+
/**
|
|
101
|
+
* Meters exposure on `face`, a box from the face analyzer, or on the whole frame when null.
|
|
102
|
+
* kamera decides when the camera actually re-meters, so it is called on every analysed frame.
|
|
103
|
+
*/
|
|
104
|
+
meterExposure(face: BoundingBox | null): void;
|
|
55
105
|
/** Releases the native session. The system is unusable afterwards. */
|
|
56
106
|
release(): Promise<void>;
|
|
57
107
|
private _onKameraEvent;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";import{KameraSession as
|
|
1
|
+
"use strict";import{AspectRatio as f,KameraSession as p}from"@smileid/kamera";import{UseSmileIDCrashReporting as l}from"@smileid/usesmileid_bridge";import{Platform as S}from"react-native";import{CaptureType as c}from"../core/models/ml_config";import{captureDebugBoxesMirrored as g}from"../debug/capture_debug_geometry";import{meteringRegion as w}from"./bounding_box_metering_region";import{CameraDefaults as h}from"./camera_defaults";import{CameraLens as a}from"./camera_lens";import{FocusStates as n}from"./focus_state";import{KameraConfigFactory as _}from"./kamera_config_factory";let m=!1,o=null;export function setKameraMetricsWanted(i){m=i}async function y(i){const e=m;if(e===o)return;o=e;const t=Promise.resolve().then(()=>i.setMetricsEnabled?.(e)).catch(s=>{o=null,l.captureException(s instanceof Error?s:new Error(String(s)))});e&&await t}export function resetKameraMetricsForTesting(){m=!1,o=null}export class UseSmileIDKameraCameraSystem{_createSession;_session=null;_removeEventListener=null;_state;_focusState=n.unspecified();_listeners=new Set;_eventListeners=new Set;_capabilities=null;_config={};_released=!1;_focusRunningTimeout=null;_focusSettledTimeout=null;constructor(e=a.front,t=()=>new p){this._createSession=t,this._state={isCameraRunning:!1,isStreaming:!1,currentLens:e,hasPermission:!1}}get state(){return this._state}get focusState(){return this._focusState}get capabilities(){return this._capabilities}get uprightPreviewAspect(){const e=this._config.captureType??c.selfie;return _.create(e,this._state.currentLens).preview.aspectRatio===f.Ratio16x9?9/16:3/4}get session(){return this._session}subscribe(e){return this._listeners.add(e),()=>this._listeners.delete(e)}addEventListener(e){return this._eventListeners.add(e),()=>this._eventListeners.delete(e)}configure(e){this._config=e,e.lens&&e.lens!==this._state.currentLens&&this._setState({...this._state,currentLens:e.lens})}async start(){if(this._released)throw new Error("UseSmileIDKameraCameraSystem.start() after release() \u2014 create a new system.");await this._teardownSession();const e=this._createSession(),t=e.addEventListener(u=>this._onKameraEvent(u)),s=this._config.captureType??c.selfie,r=this._config.lens??(s===c.document?a.back:a.front);try{await y(e),await e.start(_.create(s,r)),this._capabilities=await e.capabilities()}catch(u){throw t(),await e.release(),u}this._removeEventListener=t,this._session=e,this._documentGuideApplied=this._documentGuide===null,await this._applyDocumentGuide(),this._setState({...this._state,isCameraRunning:!0,isStreaming:!0,currentLens:r,hasPermission:!0})}async stop(){await this._session?.stop(),this._setState({...this._state,isCameraRunning:!1,isStreaming:!1})}async capture(){const e=this._session;if(!e)throw new Error("Cannot capture: camera is not initialised.");return e.capture()}async setZoomRatio(e){const t=this._session;if(!t)return;const s=this._capabilities,r=s?Math.min(s.maxZoomRatio,Math.max(s.minZoomRatio,e)):e;await t.setZoomRatio(r)}_documentGuide=null;_documentGuideApplied=!0;_documentGuideSendingTo=null;_documentGuideFailureReported=!1;async setDocumentGuide(e){d(e,this._documentGuide)||(this._documentGuide=e,this._documentGuideApplied=!1),await this._applyDocumentGuide()}async _applyDocumentGuide(){const e=this._session;if(!(e===null||this._documentGuideApplied||this._documentGuideSendingTo===e)){this._documentGuideSendingTo=e;try{for(;!this._documentGuideApplied&&this._session===e;){const t=this._documentGuide;if(!await this._sendDocumentGuide(e,t))return;this._session===e&&d(t,this._documentGuide)&&(this._documentGuideApplied=!0)}}finally{this._documentGuideSendingTo===e&&(this._documentGuideSendingTo=null)}}}async _sendDocumentGuide(e,t){try{return await e.setDocumentGuide?.(t?.widthMm??0,t?.frameWidthFraction??0),!0}catch(s){return this._documentGuideFailureReported||(this._documentGuideFailureReported=!0,l.captureException(s instanceof Error?s:new Error(String(s)))),!1}}async setTorch(e){await this._session?.setTorch(e)}async tapToFocus(e){const t=this._session;t&&(this._clearFocusTimers(),this._setFocusState(n.running(e)),t.tapToFocus(e.x,e.y).catch(()=>{this._clearFocusTimers(),this._setFocusState(n.unspecified())}),this._focusRunningTimeout=setTimeout(()=>{this._setFocusState(n.success(e)),this._focusSettledTimeout=setTimeout(()=>{this._setFocusState(n.unspecified())},h.focusSettledDurationMs)},h.focusRunningDurationMs))}meterExposure(e){const t=this._session;if(!t)return;const s=e?w(e,g(this._state.currentLens===a.front,S.OS==="android")):null;t.setMeteringRegion?.(s).catch(()=>{})}async release(){this._released=!0,this._clearFocusTimers(),await this._teardownSession(),this._setState({...this._state,isCameraRunning:!1,isStreaming:!1})}_onKameraEvent(e){for(const t of[...this._eventListeners])t(e);e.type==="error"&&this._setState({...this._state,isStreaming:!1})}async _teardownSession(){this._removeEventListener?.(),this._removeEventListener=null;const e=this._session;this._session=null,this._capabilities=null,e&&await e.release()}_clearFocusTimers(){this._focusRunningTimeout&&clearTimeout(this._focusRunningTimeout),this._focusSettledTimeout&&clearTimeout(this._focusSettledTimeout),this._focusRunningTimeout=null,this._focusSettledTimeout=null}_setState(e){this._state=e,this._notify()}_setFocusState(e){this._focusState=e,this._notify()}_notify(){for(const e of[...this._listeners])e(this._state,this._focusState)}}function d(i,e){return i?.widthMm===e?.widthMm&&i?.frameWidthFraction===e?.frameWidthFraction}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";import{JobType as e}from"../../core/models/job_type";import{UseSmileIDBuilderException as i}from"./use_smile_id_builder_exception";import{UseSmileIDErrorCode as r}from"./use_smile_id_error_code";export class InvalidJobTypeScreenConfigException extends i{errorCode=r.Builder.InvalidJobTypeScreenConfig;constructor(n){super({message:n.message,suggestedFix:n.suggestedFix??"Adjust the screens block to match the configured jobType."})}static forJob(n){const t=jobTypeName(n.jobType);return new InvalidJobTypeScreenConfigException({message:`Invalid configuration for ${t}: ${n.reason}`,suggestedFix:n.suggestedFix})}}const c=new Map([[e.biometricKyc,"BiometricKyc"],[e.smartSelfieAuthentication,"SmartSelfieAuthentication"],[e.smartSelfieEnrollment,"SmartSelfieEnrollment"],[e.enhancedKyc,"EnhancedKyc"],[e.documentVerification,"DocumentVerification"],[e.bvn,"BVN"],[e.enhancedDocumentVerification,"EnhancedDocumentVerification"],[e.unknown,"Unknown"]]);export function jobTypeName(o){return c.get(o)??"Unknown"}
|
|
1
|
+
"use strict";import{JobType as e}from"../../core/models/job_type";import{UseSmileIDBuilderException as i}from"./use_smile_id_builder_exception";import{UseSmileIDErrorCode as r}from"./use_smile_id_error_code";export class InvalidJobTypeScreenConfigException extends i{errorCode=r.Builder.InvalidJobTypeScreenConfig;constructor(n){super({message:n.message,suggestedFix:n.suggestedFix??"Adjust the screens block to match the configured jobType."})}static forJob(n){const t=jobTypeName(n.jobType);return new InvalidJobTypeScreenConfigException({message:`Invalid configuration for ${t}: ${n.reason}`,suggestedFix:n.suggestedFix})}}const c=new Map([[e.biometricKyc,"BiometricKyc"],[e.smartSelfieAuthentication,"SmartSelfieAuthentication"],[e.smartSelfieEnrollment,"SmartSelfieEnrollment"],[e.enhancedKyc,"EnhancedKyc"],[e.documentVerification,"DocumentVerification"],[e.bvn,"BVN"],[e.enhancedDocumentVerification,"EnhancedDocumentVerification"],[e.residencyDocumentVerification,"ResidencyDocumentVerification"],[e.unknown,"Unknown"]]);export function jobTypeName(o){return c.get(o)??"Unknown"}
|
|
@@ -18,4 +18,6 @@ export declare class MissingPartnerConfigException extends UseSmileIDBuilderExce
|
|
|
18
18
|
static controlCharacterPartnerId(): MissingPartnerConfigException;
|
|
19
19
|
/** The auth `token` contains a control character (usually a pasted newline). */
|
|
20
20
|
static controlCharacterAuthToken(): MissingPartnerConfigException;
|
|
21
|
+
/** The `callbackUrl` is a value the server could not resolve. */
|
|
22
|
+
static unresolvableCallbackUrl(): MissingPartnerConfigException;
|
|
21
23
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";import{UseSmileIDBuilderException as
|
|
1
|
+
"use strict";import{UseSmileIDBuilderException as t}from"./use_smile_id_builder_exception";import{UseSmileIDErrorCode as r}from"./use_smile_id_error_code";export class MissingPartnerConfigException extends t{errorCode=r.Builder.InvalidConfiguration;constructor(e){super({message:e.message,suggestedFix:`Configure the missing field '${e.fieldName}' in the network config block.`,errorDetails:{fieldName:e.fieldName}})}static missingPartnerId(){return new MissingPartnerConfigException({message:"Partner ID is required but was not configured",fieldName:"partnerId"})}static missingAuthToken(){return new MissingPartnerConfigException({message:"Auth token is required but was not configured",fieldName:"authToken"})}static controlCharacterPartnerId(){return new MissingPartnerConfigException({message:"Partner ID must not contain control characters",fieldName:"partnerId"})}static controlCharacterAuthToken(){return new MissingPartnerConfigException({message:"Auth token must not contain control characters",fieldName:"authToken"})}static unresolvableCallbackUrl(){return new MissingPartnerConfigException({message:"Callback URL must be left unset, an absolute http or https URL, or a callback ID",fieldName:"callbackUrl"})}}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";import{JobType as
|
|
1
|
+
"use strict";import{JobType as i}from"../../core/models/job_type";import{jobTypeName as n}from"./invalid_job_type_screen_config_exception";import{IssueSeverity as t}from"./issue_severity";import{UseSmileIDBuilderException as a}from"./use_smile_id_builder_exception";import{UseSmileIDErrorCode as d}from"./use_smile_id_error_code";export const JOB_PARAMS_OWNERS=[{fieldName:"enhancedKYCParams",owner:i.enhancedKyc},{fieldName:"biometricKYCParams",owner:i.biometricKyc},{fieldName:"documentVerificationParams",owner:i.documentVerification},{fieldName:"enhancedDocumentVerificationParams",owner:i.enhancedDocumentVerification},{fieldName:"residencyDocumentVerificationParams",owner:i.residencyDocumentVerification}];function c(o){return JOB_PARAMS_OWNERS.find(e=>e.fieldName===o)?.owner}export class UnusedJobParamsException extends a{errorCode=d.Builder.UnusedJobParams;fieldName;constructor(e){const r=c(e.fieldName),m=r===void 0?`Remove builder.${e.fieldName} \u2014 the configured job type does not read it`:`Remove builder.${e.fieldName} \u2014 it belongs to ${n(r)} jobs`;super({message:`${e.fieldName} is set but ${n(e.jobType)} jobs never read it`,severity:t.warning,suggestedFix:m}),this.fieldName=e.fieldName}}
|
|
@@ -56,6 +56,7 @@ export declare const UseSmileIDErrorCode: {
|
|
|
56
56
|
readonly NotFound: "NETWORK_NOT_FOUND";
|
|
57
57
|
readonly RateLimit: "NETWORK_RATE_LIMIT";
|
|
58
58
|
readonly ServerError: "NETWORK_SERVER_ERROR";
|
|
59
|
+
readonly CallbackUrlRequired: "NETWORK_CALLBACK_URL_REQUIRED";
|
|
59
60
|
};
|
|
60
61
|
/** Generic input / state validation. */
|
|
61
62
|
readonly Validation: {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";export const UseSmileIDErrorCode={Builder:{ValidationError:"BUILDER_VALIDATION_ERROR",InvalidConfiguration:"BUILDER_INVALID_CONFIG",MissingRequiredField:"BUILDER_MISSING_FIELD",InvalidConsentConfig:"BUILDER_INVALID_CONSENT_CONFIG",MissingCaptureType:"BUILDER_MISSING_CAPTURE_TYPE",EmptyScreensBlock:"BUILDER_EMPTY_SCREENS",MissingScreenConfiguration:"BUILDER_MISSING_SCREEN_CONFIG",DuplicateScreenType:"BUILDER_DUPLICATE_SCREEN",InvalidSelfieCaptureConfig:"BUILDER_INVALID_SELFIE_CONFIG",AgentModeWithEnhancedLiveness:"BUILDER_AGENT_MODE_WITH_ENHANCED_LIVENESS",InvalidDocumentCaptureConfig:"BUILDER_INVALID_DOCUMENT_CONFIG",MissingMLConfiguration:"BUILDER_MISSING_ML_CONFIG",MissingNetworkConfiguration:"BUILDER_MISSING_NETWORK_CONFIG",MissingJobType:"BUILDER_MISSING_JOB_TYPE",MissingCaptureForPreview:"BUILDER_MISSING_CAPTURE_FOR_PREVIEW",InvalidScreenOrder:"BUILDER_INVALID_SCREEN_ORDER",ConfigurationBlockFailed:"BUILDER_CONFIG_BLOCK_FAILED",InvalidConsentInformation:"BUILDER_INVALID_CONSENT_INFORMATION",InvalidJobTypeScreenConfig:"BUILDER_INVALID_JOB_TYPE_SCREEN_CONFIG",UnusedJobParams:"BUILDER_UNUSED_JOB_PARAMS"},Camera:{InitializationFailed:"CAMERA_INIT_FAILED",PermissionDenied:"CAMERA_PERMISSION_DENIED",CaptureFailed:"CAMERA_CAPTURE_FAILED",UseCaseNotSupported:"CAMERA_USE_CASE_NOT_SUPPORTED",VideoCaptureDisabled:"CAMERA_VIDEO_DISABLED",Unknown:"CAMERA_UNKNOWN_ERROR"},Network:{ConnectionFailed:"NETWORK_CONNECTION_FAILED",Timeout:"NETWORK_TIMEOUT",RequestFailed:"NETWORK_REQUEST_FAILED",ResponseParseError:"NETWORK_PARSE_ERROR",Unauthorized:"NETWORK_UNAUTHORIZED",Forbidden:"NETWORK_FORBIDDEN",NotFound:"NETWORK_NOT_FOUND",RateLimit:"NETWORK_RATE_LIMIT",ServerError:"NETWORK_SERVER_ERROR"},Validation:{InvalidInput:"VALIDATION_INVALID_INPUT",InvalidState:"VALIDATION_INVALID_STATE",ConstraintViolation:"VALIDATION_CONSTRAINT_VIOLATION"},General:{Unknown:"GENERAL_UNKNOWN_ERROR",InvalidState:"GENERAL_INVALID_STATE",OperationFailed:"GENERAL_OPERATION_FAILED"}};const I=new Set([UseSmileIDErrorCode.Camera.CaptureFailed,UseSmileIDErrorCode.Network.ConnectionFailed,UseSmileIDErrorCode.Network.Timeout,UseSmileIDErrorCode.Network.
|
|
1
|
+
"use strict";export const UseSmileIDErrorCode={Builder:{ValidationError:"BUILDER_VALIDATION_ERROR",InvalidConfiguration:"BUILDER_INVALID_CONFIG",MissingRequiredField:"BUILDER_MISSING_FIELD",InvalidConsentConfig:"BUILDER_INVALID_CONSENT_CONFIG",MissingCaptureType:"BUILDER_MISSING_CAPTURE_TYPE",EmptyScreensBlock:"BUILDER_EMPTY_SCREENS",MissingScreenConfiguration:"BUILDER_MISSING_SCREEN_CONFIG",DuplicateScreenType:"BUILDER_DUPLICATE_SCREEN",InvalidSelfieCaptureConfig:"BUILDER_INVALID_SELFIE_CONFIG",AgentModeWithEnhancedLiveness:"BUILDER_AGENT_MODE_WITH_ENHANCED_LIVENESS",InvalidDocumentCaptureConfig:"BUILDER_INVALID_DOCUMENT_CONFIG",MissingMLConfiguration:"BUILDER_MISSING_ML_CONFIG",MissingNetworkConfiguration:"BUILDER_MISSING_NETWORK_CONFIG",MissingJobType:"BUILDER_MISSING_JOB_TYPE",MissingCaptureForPreview:"BUILDER_MISSING_CAPTURE_FOR_PREVIEW",InvalidScreenOrder:"BUILDER_INVALID_SCREEN_ORDER",ConfigurationBlockFailed:"BUILDER_CONFIG_BLOCK_FAILED",InvalidConsentInformation:"BUILDER_INVALID_CONSENT_INFORMATION",InvalidJobTypeScreenConfig:"BUILDER_INVALID_JOB_TYPE_SCREEN_CONFIG",UnusedJobParams:"BUILDER_UNUSED_JOB_PARAMS"},Camera:{InitializationFailed:"CAMERA_INIT_FAILED",PermissionDenied:"CAMERA_PERMISSION_DENIED",CaptureFailed:"CAMERA_CAPTURE_FAILED",UseCaseNotSupported:"CAMERA_USE_CASE_NOT_SUPPORTED",VideoCaptureDisabled:"CAMERA_VIDEO_DISABLED",Unknown:"CAMERA_UNKNOWN_ERROR"},Network:{ConnectionFailed:"NETWORK_CONNECTION_FAILED",Timeout:"NETWORK_TIMEOUT",RequestFailed:"NETWORK_REQUEST_FAILED",ResponseParseError:"NETWORK_PARSE_ERROR",Unauthorized:"NETWORK_UNAUTHORIZED",Forbidden:"NETWORK_FORBIDDEN",NotFound:"NETWORK_NOT_FOUND",RateLimit:"NETWORK_RATE_LIMIT",ServerError:"NETWORK_SERVER_ERROR",CallbackUrlRequired:"NETWORK_CALLBACK_URL_REQUIRED"},Validation:{InvalidInput:"VALIDATION_INVALID_INPUT",InvalidState:"VALIDATION_INVALID_STATE",ConstraintViolation:"VALIDATION_CONSTRAINT_VIOLATION"},General:{Unknown:"GENERAL_UNKNOWN_ERROR",InvalidState:"GENERAL_INVALID_STATE",OperationFailed:"GENERAL_OPERATION_FAILED"}};const I=new Set([UseSmileIDErrorCode.Camera.CaptureFailed,UseSmileIDErrorCode.Network.ConnectionFailed,UseSmileIDErrorCode.Network.Timeout,UseSmileIDErrorCode.Network.RateLimit,UseSmileIDErrorCode.Network.ServerError]),e=new Set(Object.values(UseSmileIDErrorCode.Network));export function isRetryableErrorCode(E){return I.has(E)}export function isNetworkErrorCode(E){return e.has(E)}
|
|
@@ -34,20 +34,25 @@ export declare abstract class UseSmileIDNetworkException extends UseSmileIDExcep
|
|
|
34
34
|
export declare class NetworkServerException extends UseSmileIDNetworkException {
|
|
35
35
|
readonly errorCode: NetworkCode;
|
|
36
36
|
readonly statusCode: number;
|
|
37
|
-
constructor({ statusCode, cause, message, errorDetails, }: {
|
|
37
|
+
constructor({ statusCode, cause, message, errorDetails, errorCode, }: {
|
|
38
38
|
readonly statusCode: number;
|
|
39
39
|
readonly cause?: unknown;
|
|
40
40
|
readonly message?: string;
|
|
41
41
|
readonly errorDetails?: Readonly<Record<string, unknown>>;
|
|
42
|
+
readonly errorCode?: NetworkCode;
|
|
42
43
|
});
|
|
43
44
|
}
|
|
44
|
-
/**
|
|
45
|
+
/**
|
|
46
|
+
* Network reachability / DNS / TLS / socket failure — never reached the server. A cancelled
|
|
47
|
+
* request carries `NETWORK_REQUEST_FAILED`, which isn't retried.
|
|
48
|
+
*/
|
|
45
49
|
export declare class NetworkTransportException extends UseSmileIDNetworkException {
|
|
46
50
|
readonly errorCode: NetworkCode;
|
|
47
|
-
constructor({ cause, message, errorDetails, }?: {
|
|
51
|
+
constructor({ cause, message, errorDetails, errorCode, }?: {
|
|
48
52
|
readonly cause?: unknown;
|
|
49
53
|
readonly message?: string;
|
|
50
54
|
readonly errorDetails?: Readonly<Record<string, unknown>>;
|
|
55
|
+
readonly errorCode?: NetworkCode;
|
|
51
56
|
});
|
|
52
57
|
}
|
|
53
58
|
/** Request exceeded the configured timeout. Specialised transport failure. */
|
|
@@ -106,11 +111,14 @@ export declare class NetworkUnknownException extends UseSmileIDNetworkException
|
|
|
106
111
|
* server).
|
|
107
112
|
* - `AxiosError` with `response` → [NetworkServerException] carrying
|
|
108
113
|
* the wire status code; status routing via [statusToErrorCode]
|
|
109
|
-
* covers 401/403/404/429/5xx + a generic fallback.
|
|
114
|
+
* covers 401/403/404/408/429/5xx + a generic fallback. A 408 keeps this
|
|
115
|
+
* type, with its `statusCode`, and carries `NETWORK_TIMEOUT`.
|
|
110
116
|
* - Already-typed [UseSmileIDNetworkException] → pass-through so the
|
|
111
117
|
* mapper is safe to call idempotently across retry / wrap paths.
|
|
112
118
|
* - Anything else → [NetworkUnknownException] with the underlying
|
|
113
119
|
* value preserved as `cause` for triage.
|
|
114
120
|
*/
|
|
115
121
|
export declare function mapAxiosError(error: unknown): UseSmileIDNetworkException;
|
|
122
|
+
/** axios's code for a request aborted through a signal or cancel token. */
|
|
123
|
+
export declare const CANCELED = "ERR_CANCELED";
|
|
116
124
|
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";import{isAxiosError as
|
|
1
|
+
"use strict";import{isAxiosError as a}from"axios";import{UseSmileIDErrorCode as r}from"./use_smile_id_error_code";import{UseSmileIDException as c}from"./use_smile_id_exception";export class UseSmileIDNetworkException extends c{}export class NetworkServerException extends UseSmileIDNetworkException{errorCode;statusCode;constructor({statusCode:t,cause:s,message:o,errorDetails:n,errorCode:i}){super({message:o??`HTTP ${t}`,suggestedFix:"Inspect the server response body and retry if the failure is transient.",cause:s,errorDetails:n}),this.statusCode=t,this.errorCode=i??u(t)}}export class NetworkTransportException extends UseSmileIDNetworkException{errorCode;constructor({cause:t,message:s="Network transport failure.",errorDetails:o,errorCode:n=r.Network.ConnectionFailed}={}){super({message:s,suggestedFix:"Check the device's network connection and verify the configured base URL is reachable.",cause:t,errorDetails:o}),this.errorCode=n}}export class NetworkTimeoutException extends UseSmileIDNetworkException{errorCode=r.Network.Timeout;constructor({cause:t,message:s="The request timed out.",errorDetails:o}={}){super({message:s,suggestedFix:"Increase the timeout via `n.timeouts(...)` if appropriate, or retry once connectivity recovers.",cause:t,errorDetails:o})}}export class NetworkResponseParseException extends UseSmileIDNetworkException{errorCode=r.Network.ResponseParseError;constructor({cause:t,message:s="Failed to parse response body.",errorDetails:o}={}){super({message:s,suggestedFix:"Confirm the SDK version matches the backend's response schema.",cause:t,errorDetails:o})}}export class NetworkRequestBuildException extends UseSmileIDNetworkException{errorCode=r.Network.RequestFailed;constructor({cause:t,message:s="Failed to build request.",errorDetails:o}={}){super({message:s,suggestedFix:"Verify the request payload satisfies the multipart / URL contract before submission.",cause:t,errorDetails:o})}}export class NetworkUnknownException extends UseSmileIDNetworkException{errorCode=r.Network.RequestFailed;constructor({cause:t,message:s="Unknown network error.",errorDetails:o}={}){super({message:s,suggestedFix:"Log the wrapped `cause` for triage \u2014 anything reaching this branch represents a gap in error mapping.",cause:t,errorDetails:o})}}function u(e){return e===401?r.Network.Unauthorized:e===403?r.Network.Forbidden:e===404?r.Network.NotFound:e===408?r.Network.Timeout:e===429?r.Network.RateLimit:e>=500&&e<600?r.Network.ServerError:r.Network.RequestFailed}export function mapAxiosError(e){return e instanceof UseSmileIDNetworkException?e:a(e)?d(e):e instanceof Error?new NetworkUnknownException({message:e.message,cause:e}):new NetworkUnknownException({message:String(e),cause:e})}function d(e){if(e.code==="ERR_BAD_OPTION"||e.code==="ERR_BAD_OPTION_VALUE"||e.code==="ERR_INVALID_URL")return new NetworkRequestBuildException({message:e.message,cause:e});if(e.code===CANCELED)return new NetworkTransportException({message:e.message,cause:e,errorCode:r.Network.RequestFailed});if(e.code==="ECONNABORTED")return new NetworkTimeoutException({message:e.message,cause:e});if(!e.response)return new NetworkTransportException({message:e.message,cause:e});const t=e.response.status,s=e.response.data;return new NetworkServerException({statusCode:t,message:s?.message??`HTTP ${t}: ${e.message}`,cause:e,...s?.message?.trim()===p?{errorCode:r.Network.CallbackUrlRequired}:{}})}export const CANCELED="ERR_CANCELED";const p="A valid callback_url is required in the request or a default callback URL must be configured in the portal.";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";export function isDevelopmentBuild(){return typeof __DEV__<"u"&&__DEV__}
|
|
@@ -33,6 +33,12 @@ export type ConfigOptions = {
|
|
|
33
33
|
* `docs/Architecture.md § Rollout`.
|
|
34
34
|
*/
|
|
35
35
|
readonly allowOfflineMode: boolean;
|
|
36
|
+
/**
|
|
37
|
+
* Hand the captured job back through `onResult` as `{ status: "captured" }`
|
|
38
|
+
* instead of submitting it. The captured files are kept on disk for you to
|
|
39
|
+
* forward and delete. Absent reads as `false`.
|
|
40
|
+
*/
|
|
41
|
+
readonly skipApiSubmission?: boolean;
|
|
36
42
|
/**
|
|
37
43
|
* Journey-wide "Powered by Smile ID" branding; document capture never shows
|
|
38
44
|
* it. Defaults to `true`.
|
|
@@ -35,7 +35,7 @@ export declare const DocumentType: {
|
|
|
35
35
|
readonly SouthAfricaGreenBook: {
|
|
36
36
|
readonly kind: "southAfricaGreenBook";
|
|
37
37
|
} & DocumentTypeFields;
|
|
38
|
-
/** Passport — landscape data page
|
|
38
|
+
/** Passport — landscape data page. */
|
|
39
39
|
readonly Passport: {
|
|
40
40
|
readonly kind: "passport";
|
|
41
41
|
} & DocumentTypeFields;
|