@scalebun/react-native 1.0.0 → 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (1564) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +65 -66
  3. package/android/build/generated/source/buildConfig/debug/com/scalebun/sdk/BuildConfig.java +12 -0
  4. package/android/build/generated/source/codegen/java/com/scalebun/spec/NativeReplaySdkSpec.java +208 -0
  5. package/android/build/generated/source/codegen/java/com/scalebun/spec/NativeScaleBunCrashSpec.java +46 -0
  6. package/android/build/generated/source/codegen/java/com/scalebun/spec/NativeScaleBunInstallReferrerSpec.java +38 -0
  7. package/android/build/generated/source/codegen/java/com/scalebun/spec/NativeScaleBunOtaSpec.java +63 -0
  8. package/android/build/generated/source/codegen/java/com/scalebun/spec/NativeScaleBunPerformanceSpec.java +70 -0
  9. package/android/build/generated/source/codegen/java/com/scalebun/spec/NativeScaleBunProfilerSpec.java +96 -0
  10. package/android/build/generated/source/codegen/java/com/scalebun/spec/NativeScaleBunStorageSpec.java +50 -0
  11. package/android/build/generated/source/codegen/jni/CMakeLists.txt +28 -0
  12. package/android/build/generated/source/codegen/jni/ScaleBunSpec-generated.cpp +554 -0
  13. package/android/build/generated/source/codegen/jni/ScaleBunSpec.h +79 -0
  14. package/android/build/generated/source/codegen/jni/react/renderer/components/ScaleBunSpec/ComponentDescriptors.cpp +22 -0
  15. package/android/build/generated/source/codegen/jni/react/renderer/components/ScaleBunSpec/ComponentDescriptors.h +24 -0
  16. package/android/build/generated/source/codegen/jni/react/renderer/components/ScaleBunSpec/EventEmitters.cpp +16 -0
  17. package/android/build/generated/source/codegen/jni/react/renderer/components/ScaleBunSpec/EventEmitters.h +17 -0
  18. package/android/build/generated/source/codegen/jni/react/renderer/components/ScaleBunSpec/Props.cpp +19 -0
  19. package/android/build/generated/source/codegen/jni/react/renderer/components/ScaleBunSpec/Props.h +18 -0
  20. package/android/build/generated/source/codegen/jni/react/renderer/components/ScaleBunSpec/ScaleBunSpecJSI-generated.cpp +595 -0
  21. package/android/build/generated/source/codegen/jni/react/renderer/components/ScaleBunSpec/ScaleBunSpecJSI.h +1070 -0
  22. package/android/build/generated/source/codegen/jni/react/renderer/components/ScaleBunSpec/ShadowNodes.cpp +17 -0
  23. package/android/build/generated/source/codegen/jni/react/renderer/components/ScaleBunSpec/ShadowNodes.h +23 -0
  24. package/android/build/generated/source/codegen/jni/react/renderer/components/ScaleBunSpec/States.cpp +16 -0
  25. package/android/build/generated/source/codegen/jni/react/renderer/components/ScaleBunSpec/States.h +20 -0
  26. package/android/build/generated/source/codegen/schema.json +1 -0
  27. package/android/build/intermediates/aapt_friendly_merged_manifests/debug/processDebugManifest/aapt/AndroidManifest.xml +20 -0
  28. package/android/build/intermediates/aapt_friendly_merged_manifests/debug/processDebugManifest/aapt/output-metadata.json +18 -0
  29. package/android/build/intermediates/aar_metadata/debug/writeDebugAarMetadata/aar-metadata.properties +6 -0
  30. package/android/build/intermediates/annotation_processor_list/debug/javaPreCompileDebug/annotationProcessors.json +1 -0
  31. package/android/build/intermediates/compile_library_classes_jar/debug/bundleLibCompileToJarDebug/classes.jar +0 -0
  32. package/android/build/intermediates/compile_r_class_jar/debug/generateDebugRFile/R.jar +0 -0
  33. package/android/build/intermediates/compile_symbol_list/debug/generateDebugRFile/R.txt +0 -0
  34. package/android/build/intermediates/incremental/debug/packageDebugResources/compile-file-map.properties +1 -0
  35. package/android/build/intermediates/incremental/debug/packageDebugResources/merger.xml +2 -0
  36. package/android/build/intermediates/incremental/mergeDebugAssets/merger.xml +2 -0
  37. package/android/build/intermediates/incremental/mergeDebugJniLibFolders/merger.xml +2 -0
  38. package/android/build/intermediates/incremental/mergeDebugShaders/merger.xml +2 -0
  39. package/android/build/intermediates/java_res/debug/processDebugJavaRes/out/META-INF/scalebun_react-native_debug.kotlin_module +0 -0
  40. package/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/scalebun/sdk/BuildConfig.class +0 -0
  41. package/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/scalebun/spec/NativeReplaySdkSpec.class +0 -0
  42. package/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/scalebun/spec/NativeScaleBunCrashSpec.class +0 -0
  43. package/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/scalebun/spec/NativeScaleBunInstallReferrerSpec.class +0 -0
  44. package/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/scalebun/spec/NativeScaleBunOtaSpec.class +0 -0
  45. package/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/scalebun/spec/NativeScaleBunPerformanceSpec.class +0 -0
  46. package/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/scalebun/spec/NativeScaleBunProfilerSpec.class +0 -0
  47. package/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/scalebun/spec/NativeScaleBunStorageSpec.class +0 -0
  48. package/android/build/intermediates/local_only_symbol_list/debug/parseDebugLocalResources/R-def.txt +2 -0
  49. package/android/build/intermediates/manifest_merge_blame_file/debug/processDebugManifest/manifest-merger-blame-debug-report.txt +24 -0
  50. package/android/build/intermediates/merged_manifest/debug/processDebugManifest/AndroidManifest.xml +20 -0
  51. package/android/build/intermediates/navigation_json/debug/extractDeepLinksDebug/navigation.json +1 -0
  52. package/android/build/intermediates/nested_resources_validation_report/debug/generateDebugResources/nestedResourcesValidationReport.txt +1 -0
  53. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/META-INF/scalebun_react-native_debug.kotlin_module +0 -0
  54. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/core/crash/CrashStorage.class +0 -0
  55. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/core/crash/NativeCrashHandler$Companion.class +0 -0
  56. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/core/crash/NativeCrashHandler.class +0 -0
  57. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/core/performance/ANRWatchdog$HangInfo.class +0 -0
  58. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/core/performance/ANRWatchdog.class +0 -0
  59. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/core/performance/AppStartCollector$AppStartInfo.class +0 -0
  60. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/core/performance/AppStartCollector$Breakdown.class +0 -0
  61. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/core/performance/AppStartCollector$start$1.class +0 -0
  62. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/core/performance/AppStartCollector.class +0 -0
  63. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/core/performance/FrameMetricsCollector$Companion.class +0 -0
  64. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/core/performance/FrameMetricsCollector$FrameMetricsSnapshot.class +0 -0
  65. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/core/performance/FrameMetricsCollector$start$1.class +0 -0
  66. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/core/performance/FrameMetricsCollector$startChoreographerFallback$1.class +0 -0
  67. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/core/performance/FrameMetricsCollector.class +0 -0
  68. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/core/performance/PerformanceCore$Listener.class +0 -0
  69. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/core/performance/PerformanceCore.class +0 -0
  70. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/profiler/ProfilerModule$Companion.class +0 -0
  71. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/profiler/ProfilerModule.class +0 -0
  72. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/profiler/ProfilerPackage.class +0 -0
  73. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/profiler/ProfilerSpec.class +0 -0
  74. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/profiler/collectors/CpuCollector.class +0 -0
  75. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/profiler/collectors/IncidentDetector.class +0 -0
  76. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/profiler/collectors/MemoryCollector.class +0 -0
  77. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/profiler/collectors/RenderCollector$frameCallback$1.class +0 -0
  78. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/profiler/collectors/RenderCollector.class +0 -0
  79. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/profiler/collectors/SamplerScheduler.class +0 -0
  80. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/profiler/collectors/SamplerSchedulerKt.class +0 -0
  81. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/profiler/collectors/ThreadCollector$WhenMappings.class +0 -0
  82. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/profiler/collectors/ThreadCollector.class +0 -0
  83. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/replaysdk/ReplaySdkModule$Companion.class +0 -0
  84. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/replaysdk/ReplaySdkModule$registerConnectivity$cb$1.class +0 -0
  85. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/replaysdk/ReplaySdkModule.class +0 -0
  86. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/replaysdk/ReplaySdkPackage.class +0 -0
  87. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/replaysdk/ReplaySdkSpec.class +0 -0
  88. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/replaysdk/capture/CaptureReason$Companion.class +0 -0
  89. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/replaysdk/capture/CaptureReason.class +0 -0
  90. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/replaysdk/capture/FrameCaptureManager$startFrequencyTimer$1.class +0 -0
  91. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/replaysdk/capture/FrameCaptureManager.class +0 -0
  92. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/replaysdk/capture/FrameCaptureScheduler$Companion.class +0 -0
  93. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/replaysdk/capture/FrameCaptureScheduler$FrameRequest.class +0 -0
  94. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/replaysdk/capture/FrameCaptureScheduler.class +0 -0
  95. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/replaysdk/capture/UiStabilityDetector$Companion.class +0 -0
  96. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/replaysdk/capture/UiStabilityDetector$SettleWatch.class +0 -0
  97. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/replaysdk/capture/UiStabilityDetector$StabilityWatch.class +0 -0
  98. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/replaysdk/capture/UiStabilityDetector.class +0 -0
  99. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/replaysdk/core/CaptureMode$Companion.class +0 -0
  100. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/replaysdk/core/CaptureMode.class +0 -0
  101. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/replaysdk/core/ReplayConfig$Companion.class +0 -0
  102. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/replaysdk/core/ReplayConfig.class +0 -0
  103. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/replaysdk/core/ReplayLogger.class +0 -0
  104. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/replaysdk/core/ScreenshotQuality$Companion.class +0 -0
  105. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/replaysdk/core/ScreenshotQuality.class +0 -0
  106. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/replaysdk/core/SessionIdGenerator.class +0 -0
  107. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/replaysdk/core/SessionState.class +0 -0
  108. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/replaysdk/models/ReplayFrame.class +0 -0
  109. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/replaysdk/models/ReplaySession.class +0 -0
  110. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/replaysdk/models/TimelineEvent.class +0 -0
  111. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/replaysdk/outbox/NativeOutbox$Companion.class +0 -0
  112. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/replaysdk/outbox/NativeOutbox$enforceLimits$lambda$37$$inlined$sortedBy$1.class +0 -0
  113. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/replaysdk/outbox/NativeOutbox.class +0 -0
  114. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/replaysdk/outbox/OutboxUploader$NetResult$NetworkError.class +0 -0
  115. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/replaysdk/outbox/OutboxUploader$NetResult$Response.class +0 -0
  116. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/replaysdk/outbox/OutboxUploader$NetResult.class +0 -0
  117. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/replaysdk/outbox/OutboxUploader$Outcome.class +0 -0
  118. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/replaysdk/outbox/OutboxUploader$WhenMappings.class +0 -0
  119. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/replaysdk/outbox/OutboxUploader.class +0 -0
  120. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/replaysdk/privacy/PrivacyMaskProcessor.class +0 -0
  121. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/replaysdk/session/SessionManager.class +0 -0
  122. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/replaysdk/storage/ReplayStorage$enforceStorageLimit$$inlined$sortedBy$1.class +0 -0
  123. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/replaysdk/storage/ReplayStorage.class +0 -0
  124. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/replaysdk/timeline/TimelineCollector.class +0 -0
  125. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/replaysdk/tracking/DialogTouchObserver$start$runnable$1.class +0 -0
  126. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/replaysdk/tracking/DialogTouchObserver.class +0 -0
  127. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/replaysdk/tracking/InteractionTracker.class +0 -0
  128. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/replaysdk/tracking/NativeTouchInterceptor.class +0 -0
  129. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/replaysdk/tracking/ScreenTracker.class +0 -0
  130. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/replaysdk/transport/ReplayTransport$UploadResult.class +0 -0
  131. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/replaysdk/transport/ReplayTransport$upload$2.class +0 -0
  132. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/replaysdk/transport/ReplayTransport.class +0 -0
  133. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/replaysdk/voice/VoiceRecorder$Companion.class +0 -0
  134. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/replaysdk/voice/VoiceRecorder$Result.class +0 -0
  135. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/replaysdk/voice/VoiceRecorder.class +0 -0
  136. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/replaysdk/voice/VoiceTranscriber$TranscriptResult.class +0 -0
  137. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/replaysdk/voice/VoiceTranscriber$listener$1.class +0 -0
  138. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/replaysdk/voice/VoiceTranscriber.class +0 -0
  139. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/rn/ScaleBunPackage$Companion.class +0 -0
  140. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/rn/ScaleBunPackage.class +0 -0
  141. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/rn/crash/ScaleBunCrashModule$Companion.class +0 -0
  142. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/rn/crash/ScaleBunCrashModule.class +0 -0
  143. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/rn/crash/ScaleBunCrashPackage.class +0 -0
  144. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/rn/crash/ScaleBunCrashSpec.class +0 -0
  145. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/rn/engage/ScaleBunEngageModule$Companion.class +0 -0
  146. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/rn/engage/ScaleBunEngageModule$WindowInsetEdges.class +0 -0
  147. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/rn/engage/ScaleBunEngageModule$shakeListener$1.class +0 -0
  148. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/rn/engage/ScaleBunEngageModule.class +0 -0
  149. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/rn/engage/ScaleBunEngagePackage.class +0 -0
  150. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/rn/engage/ScaleBunNotificationPresenter.class +0 -0
  151. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/rn/ota/ScaleBunOtaModule$Companion.class +0 -0
  152. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/rn/ota/ScaleBunOtaModule.class +0 -0
  153. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/rn/ota/ScaleBunOtaSpec.class +0 -0
  154. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/rn/ota/SlotManager$Companion.class +0 -0
  155. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/rn/ota/SlotManager.class +0 -0
  156. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/rn/performance/PerformanceModule$Companion.class +0 -0
  157. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/rn/performance/PerformanceModule$coreListener$1.class +0 -0
  158. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/rn/performance/PerformanceModule.class +0 -0
  159. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/rn/performance/PerformanceSpec.class +0 -0
  160. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/rn/referrer/ScaleBunInstallReferrerModule$Companion.class +0 -0
  161. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/rn/referrer/ScaleBunInstallReferrerModule$getInstallReferrer$1.class +0 -0
  162. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/rn/referrer/ScaleBunInstallReferrerModule.class +0 -0
  163. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/rn/referrer/ScaleBunInstallReferrerSpec.class +0 -0
  164. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/rn/storage/ScaleBunStorageModule$Companion.class +0 -0
  165. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/rn/storage/ScaleBunStorageModule.class +0 -0
  166. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/rn/storage/ScaleBunStorageSpec.class +0 -0
  167. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/sdk/BuildConfig.class +0 -0
  168. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/spec/NativeReplaySdkSpec.class +0 -0
  169. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/spec/NativeScaleBunCrashSpec.class +0 -0
  170. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/spec/NativeScaleBunInstallReferrerSpec.class +0 -0
  171. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/spec/NativeScaleBunOtaSpec.class +0 -0
  172. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/spec/NativeScaleBunPerformanceSpec.class +0 -0
  173. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/spec/NativeScaleBunProfilerSpec.class +0 -0
  174. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/spec/NativeScaleBunStorageSpec.class +0 -0
  175. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/storage/KvFileStore$Companion.class +0 -0
  176. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/scalebun/storage/KvFileStore.class +0 -0
  177. package/android/build/intermediates/runtime_library_classes_jar/debug/bundleLibRuntimeToJarDebug/classes.jar +0 -0
  178. package/android/build/intermediates/symbol_list_with_package_name/debug/generateDebugRFile/package-aware-r.txt +1 -0
  179. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/inputs/source-to-output.tab +0 -0
  180. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/inputs/source-to-output.tab.keystream +0 -0
  181. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/inputs/source-to-output.tab.keystream.len +0 -0
  182. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/inputs/source-to-output.tab.len +0 -0
  183. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/inputs/source-to-output.tab.values.at +0 -0
  184. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/inputs/source-to-output.tab_i +0 -0
  185. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/inputs/source-to-output.tab_i.len +0 -0
  186. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab +0 -0
  187. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab.keystream +0 -0
  188. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab.keystream.len +0 -0
  189. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab.len +0 -0
  190. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab.values.at +0 -0
  191. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab_i +0 -0
  192. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab_i.len +0 -0
  193. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab +0 -0
  194. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab.keystream +0 -0
  195. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab.keystream.len +0 -0
  196. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab.len +0 -0
  197. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab.values.at +0 -0
  198. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab_i +0 -0
  199. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab_i.len +0 -0
  200. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/constants.tab +0 -0
  201. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/constants.tab.keystream +0 -0
  202. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/constants.tab.keystream.len +0 -0
  203. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/constants.tab.len +0 -0
  204. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/constants.tab.values.at +0 -0
  205. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/constants.tab_i +0 -0
  206. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/constants.tab_i.len +0 -0
  207. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab +0 -0
  208. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab.keystream +0 -0
  209. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab.keystream.len +0 -0
  210. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab.len +0 -0
  211. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab.values.at +0 -0
  212. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab_i +0 -0
  213. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab_i.len +0 -0
  214. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/package-parts.tab +0 -0
  215. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/package-parts.tab.keystream +0 -0
  216. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/package-parts.tab.keystream.len +0 -0
  217. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/package-parts.tab.len +0 -0
  218. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/package-parts.tab.values.at +0 -0
  219. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/package-parts.tab_i +0 -0
  220. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/package-parts.tab_i.len +0 -0
  221. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab +0 -0
  222. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab.keystream +0 -0
  223. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab.keystream.len +0 -0
  224. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab.len +0 -0
  225. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab.values +0 -0
  226. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab.values.at +0 -0
  227. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab.values.s +1 -0
  228. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab_i +0 -0
  229. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab_i.len +0 -0
  230. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab +0 -0
  231. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab.keystream +0 -0
  232. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab.keystream.len +0 -0
  233. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab.len +0 -0
  234. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab.values.at +0 -0
  235. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab_i +0 -0
  236. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab_i.len +0 -0
  237. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab +0 -0
  238. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab.keystream +0 -0
  239. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab.keystream.len +0 -0
  240. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab.len +0 -0
  241. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab.values.at +0 -0
  242. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab_i +0 -0
  243. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab_i.len +0 -0
  244. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab +0 -0
  245. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab.keystream +0 -0
  246. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab.keystream.len +0 -0
  247. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab.len +0 -0
  248. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab.values.at +0 -0
  249. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab_i +0 -0
  250. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab_i.len +0 -0
  251. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/counters.tab +2 -0
  252. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/file-to-id.tab +0 -0
  253. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/file-to-id.tab.keystream +0 -0
  254. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/file-to-id.tab.keystream.len +0 -0
  255. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/file-to-id.tab.len +0 -0
  256. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/file-to-id.tab.values.at +0 -0
  257. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/file-to-id.tab_i +0 -0
  258. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/file-to-id.tab_i.len +0 -0
  259. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab +0 -0
  260. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab.keystream +0 -0
  261. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab.keystream.len +0 -0
  262. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab.len +0 -0
  263. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab.values.at +0 -0
  264. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab_i +0 -0
  265. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab_i.len +0 -0
  266. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab +0 -0
  267. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab.keystream +0 -0
  268. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab.keystream.len +0 -0
  269. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab.len +0 -0
  270. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab.values +0 -0
  271. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab.values.at +0 -0
  272. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab.values.s +1 -0
  273. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab_i +0 -0
  274. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab_i.len +0 -0
  275. package/android/build/kotlin/compileDebugKotlin/cacheable/last-build.bin +0 -0
  276. package/android/build/kotlin/compileDebugKotlin/classpath-snapshot/shrunk-classpath-snapshot.bin +0 -0
  277. package/android/build/kotlin/compileDebugKotlin/local-state/build-history.bin +0 -0
  278. package/android/build/outputs/logs/manifest-merger-debug-report.txt +25 -0
  279. package/android/build/tmp/compileDebugJavaWithJavac/previous-compilation-data.bin +0 -0
  280. package/android/build/tmp/kotlin-classes/debug/META-INF/scalebun_react-native_debug.kotlin_module +0 -0
  281. package/android/build/tmp/kotlin-classes/debug/com/scalebun/core/crash/CrashStorage.class +0 -0
  282. package/android/build/tmp/kotlin-classes/debug/com/scalebun/core/crash/NativeCrashHandler$Companion.class +0 -0
  283. package/android/build/tmp/kotlin-classes/debug/com/scalebun/core/crash/NativeCrashHandler.class +0 -0
  284. package/android/build/tmp/kotlin-classes/debug/com/scalebun/core/performance/ANRWatchdog$HangInfo.class +0 -0
  285. package/android/build/tmp/kotlin-classes/debug/com/scalebun/core/performance/ANRWatchdog.class +0 -0
  286. package/android/build/tmp/kotlin-classes/debug/com/scalebun/core/performance/AppStartCollector$AppStartInfo.class +0 -0
  287. package/android/build/tmp/kotlin-classes/debug/com/scalebun/core/performance/AppStartCollector$Breakdown.class +0 -0
  288. package/android/build/tmp/kotlin-classes/debug/com/scalebun/core/performance/AppStartCollector$start$1.class +0 -0
  289. package/android/build/tmp/kotlin-classes/debug/com/scalebun/core/performance/AppStartCollector.class +0 -0
  290. package/android/build/tmp/kotlin-classes/debug/com/scalebun/core/performance/FrameMetricsCollector$Companion.class +0 -0
  291. package/android/build/tmp/kotlin-classes/debug/com/scalebun/core/performance/FrameMetricsCollector$FrameMetricsSnapshot.class +0 -0
  292. package/android/build/tmp/kotlin-classes/debug/com/scalebun/core/performance/FrameMetricsCollector$start$1.class +0 -0
  293. package/android/build/tmp/kotlin-classes/debug/com/scalebun/core/performance/FrameMetricsCollector$startChoreographerFallback$1.class +0 -0
  294. package/android/build/tmp/kotlin-classes/debug/com/scalebun/core/performance/FrameMetricsCollector.class +0 -0
  295. package/android/build/tmp/kotlin-classes/debug/com/scalebun/core/performance/PerformanceCore$Listener.class +0 -0
  296. package/android/build/tmp/kotlin-classes/debug/com/scalebun/core/performance/PerformanceCore.class +0 -0
  297. package/android/build/tmp/kotlin-classes/debug/com/scalebun/profiler/ProfilerModule$Companion.class +0 -0
  298. package/android/build/tmp/kotlin-classes/debug/com/scalebun/profiler/ProfilerModule.class +0 -0
  299. package/android/build/tmp/kotlin-classes/debug/com/scalebun/profiler/ProfilerPackage.class +0 -0
  300. package/android/build/tmp/kotlin-classes/debug/com/scalebun/profiler/ProfilerSpec.class +0 -0
  301. package/android/build/tmp/kotlin-classes/debug/com/scalebun/profiler/collectors/CpuCollector.class +0 -0
  302. package/android/build/tmp/kotlin-classes/debug/com/scalebun/profiler/collectors/IncidentDetector.class +0 -0
  303. package/android/build/tmp/kotlin-classes/debug/com/scalebun/profiler/collectors/MemoryCollector.class +0 -0
  304. package/android/build/tmp/kotlin-classes/debug/com/scalebun/profiler/collectors/RenderCollector$frameCallback$1.class +0 -0
  305. package/android/build/tmp/kotlin-classes/debug/com/scalebun/profiler/collectors/RenderCollector.class +0 -0
  306. package/android/build/tmp/kotlin-classes/debug/com/scalebun/profiler/collectors/SamplerScheduler.class +0 -0
  307. package/android/build/tmp/kotlin-classes/debug/com/scalebun/profiler/collectors/SamplerSchedulerKt.class +0 -0
  308. package/android/build/tmp/kotlin-classes/debug/com/scalebun/profiler/collectors/ThreadCollector$WhenMappings.class +0 -0
  309. package/android/build/tmp/kotlin-classes/debug/com/scalebun/profiler/collectors/ThreadCollector.class +0 -0
  310. package/android/build/tmp/kotlin-classes/debug/com/scalebun/replaysdk/ReplaySdkModule$Companion.class +0 -0
  311. package/android/build/tmp/kotlin-classes/debug/com/scalebun/replaysdk/ReplaySdkModule$registerConnectivity$cb$1.class +0 -0
  312. package/android/build/tmp/kotlin-classes/debug/com/scalebun/replaysdk/ReplaySdkModule.class +0 -0
  313. package/android/build/tmp/kotlin-classes/debug/com/scalebun/replaysdk/ReplaySdkPackage.class +0 -0
  314. package/android/build/tmp/kotlin-classes/debug/com/scalebun/replaysdk/ReplaySdkSpec.class +0 -0
  315. package/android/build/tmp/kotlin-classes/debug/com/scalebun/replaysdk/capture/CaptureReason$Companion.class +0 -0
  316. package/android/build/tmp/kotlin-classes/debug/com/scalebun/replaysdk/capture/CaptureReason.class +0 -0
  317. package/android/build/tmp/kotlin-classes/debug/com/scalebun/replaysdk/capture/FrameCaptureManager$startFrequencyTimer$1.class +0 -0
  318. package/android/build/tmp/kotlin-classes/debug/com/scalebun/replaysdk/capture/FrameCaptureManager.class +0 -0
  319. package/android/build/tmp/kotlin-classes/debug/com/scalebun/replaysdk/capture/FrameCaptureScheduler$Companion.class +0 -0
  320. package/android/build/tmp/kotlin-classes/debug/com/scalebun/replaysdk/capture/FrameCaptureScheduler$FrameRequest.class +0 -0
  321. package/android/build/tmp/kotlin-classes/debug/com/scalebun/replaysdk/capture/FrameCaptureScheduler.class +0 -0
  322. package/android/build/tmp/kotlin-classes/debug/com/scalebun/replaysdk/capture/UiStabilityDetector$Companion.class +0 -0
  323. package/android/build/tmp/kotlin-classes/debug/com/scalebun/replaysdk/capture/UiStabilityDetector$SettleWatch.class +0 -0
  324. package/android/build/tmp/kotlin-classes/debug/com/scalebun/replaysdk/capture/UiStabilityDetector$StabilityWatch.class +0 -0
  325. package/android/build/tmp/kotlin-classes/debug/com/scalebun/replaysdk/capture/UiStabilityDetector.class +0 -0
  326. package/android/build/tmp/kotlin-classes/debug/com/scalebun/replaysdk/core/CaptureMode$Companion.class +0 -0
  327. package/android/build/tmp/kotlin-classes/debug/com/scalebun/replaysdk/core/CaptureMode.class +0 -0
  328. package/android/build/tmp/kotlin-classes/debug/com/scalebun/replaysdk/core/ReplayConfig$Companion.class +0 -0
  329. package/android/build/tmp/kotlin-classes/debug/com/scalebun/replaysdk/core/ReplayConfig.class +0 -0
  330. package/android/build/tmp/kotlin-classes/debug/com/scalebun/replaysdk/core/ReplayLogger.class +0 -0
  331. package/android/build/tmp/kotlin-classes/debug/com/scalebun/replaysdk/core/ScreenshotQuality$Companion.class +0 -0
  332. package/android/build/tmp/kotlin-classes/debug/com/scalebun/replaysdk/core/ScreenshotQuality.class +0 -0
  333. package/android/build/tmp/kotlin-classes/debug/com/scalebun/replaysdk/core/SessionIdGenerator.class +0 -0
  334. package/android/build/tmp/kotlin-classes/debug/com/scalebun/replaysdk/core/SessionState.class +0 -0
  335. package/android/build/tmp/kotlin-classes/debug/com/scalebun/replaysdk/models/ReplayFrame.class +0 -0
  336. package/android/build/tmp/kotlin-classes/debug/com/scalebun/replaysdk/models/ReplaySession.class +0 -0
  337. package/android/build/tmp/kotlin-classes/debug/com/scalebun/replaysdk/models/TimelineEvent.class +0 -0
  338. package/android/build/tmp/kotlin-classes/debug/com/scalebun/replaysdk/outbox/NativeOutbox$Companion.class +0 -0
  339. package/android/build/tmp/kotlin-classes/debug/com/scalebun/replaysdk/outbox/NativeOutbox$enforceLimits$lambda$37$$inlined$sortedBy$1.class +0 -0
  340. package/android/build/tmp/kotlin-classes/debug/com/scalebun/replaysdk/outbox/NativeOutbox.class +0 -0
  341. package/android/build/tmp/kotlin-classes/debug/com/scalebun/replaysdk/outbox/OutboxUploader$NetResult$NetworkError.class +0 -0
  342. package/android/build/tmp/kotlin-classes/debug/com/scalebun/replaysdk/outbox/OutboxUploader$NetResult$Response.class +0 -0
  343. package/android/build/tmp/kotlin-classes/debug/com/scalebun/replaysdk/outbox/OutboxUploader$NetResult.class +0 -0
  344. package/android/build/tmp/kotlin-classes/debug/com/scalebun/replaysdk/outbox/OutboxUploader$Outcome.class +0 -0
  345. package/android/build/tmp/kotlin-classes/debug/com/scalebun/replaysdk/outbox/OutboxUploader$WhenMappings.class +0 -0
  346. package/android/build/tmp/kotlin-classes/debug/com/scalebun/replaysdk/outbox/OutboxUploader.class +0 -0
  347. package/android/build/tmp/kotlin-classes/debug/com/scalebun/replaysdk/privacy/PrivacyMaskProcessor.class +0 -0
  348. package/android/build/tmp/kotlin-classes/debug/com/scalebun/replaysdk/session/SessionManager.class +0 -0
  349. package/android/build/tmp/kotlin-classes/debug/com/scalebun/replaysdk/storage/ReplayStorage$enforceStorageLimit$$inlined$sortedBy$1.class +0 -0
  350. package/android/build/tmp/kotlin-classes/debug/com/scalebun/replaysdk/storage/ReplayStorage.class +0 -0
  351. package/android/build/tmp/kotlin-classes/debug/com/scalebun/replaysdk/timeline/TimelineCollector.class +0 -0
  352. package/android/build/tmp/kotlin-classes/debug/com/scalebun/replaysdk/tracking/DialogTouchObserver$start$runnable$1.class +0 -0
  353. package/android/build/tmp/kotlin-classes/debug/com/scalebun/replaysdk/tracking/DialogTouchObserver.class +0 -0
  354. package/android/build/tmp/kotlin-classes/debug/com/scalebun/replaysdk/tracking/InteractionTracker.class +0 -0
  355. package/android/build/tmp/kotlin-classes/debug/com/scalebun/replaysdk/tracking/NativeTouchInterceptor.class +0 -0
  356. package/android/build/tmp/kotlin-classes/debug/com/scalebun/replaysdk/tracking/ScreenTracker.class +0 -0
  357. package/android/build/tmp/kotlin-classes/debug/com/scalebun/replaysdk/transport/ReplayTransport$UploadResult.class +0 -0
  358. package/android/build/tmp/kotlin-classes/debug/com/scalebun/replaysdk/transport/ReplayTransport$upload$2.class +0 -0
  359. package/android/build/tmp/kotlin-classes/debug/com/scalebun/replaysdk/transport/ReplayTransport.class +0 -0
  360. package/android/build/tmp/kotlin-classes/debug/com/scalebun/replaysdk/voice/VoiceRecorder$Companion.class +0 -0
  361. package/android/build/tmp/kotlin-classes/debug/com/scalebun/replaysdk/voice/VoiceRecorder$Result.class +0 -0
  362. package/android/build/tmp/kotlin-classes/debug/com/scalebun/replaysdk/voice/VoiceRecorder.class +0 -0
  363. package/android/build/tmp/kotlin-classes/debug/com/scalebun/replaysdk/voice/VoiceTranscriber$TranscriptResult.class +0 -0
  364. package/android/build/tmp/kotlin-classes/debug/com/scalebun/replaysdk/voice/VoiceTranscriber$listener$1.class +0 -0
  365. package/android/build/tmp/kotlin-classes/debug/com/scalebun/replaysdk/voice/VoiceTranscriber.class +0 -0
  366. package/android/build/tmp/kotlin-classes/debug/com/scalebun/rn/ScaleBunPackage$Companion.class +0 -0
  367. package/android/build/tmp/kotlin-classes/debug/com/scalebun/rn/ScaleBunPackage.class +0 -0
  368. package/android/build/tmp/kotlin-classes/debug/com/scalebun/rn/crash/ScaleBunCrashModule$Companion.class +0 -0
  369. package/android/build/tmp/kotlin-classes/debug/com/scalebun/rn/crash/ScaleBunCrashModule.class +0 -0
  370. package/android/build/tmp/kotlin-classes/debug/com/scalebun/rn/crash/ScaleBunCrashPackage.class +0 -0
  371. package/android/build/tmp/kotlin-classes/debug/com/scalebun/rn/crash/ScaleBunCrashSpec.class +0 -0
  372. package/android/build/tmp/kotlin-classes/debug/com/scalebun/rn/engage/ScaleBunEngageModule$Companion.class +0 -0
  373. package/android/build/tmp/kotlin-classes/debug/com/scalebun/rn/engage/ScaleBunEngageModule$WindowInsetEdges.class +0 -0
  374. package/android/build/tmp/kotlin-classes/debug/com/scalebun/rn/engage/ScaleBunEngageModule$shakeListener$1.class +0 -0
  375. package/android/build/tmp/kotlin-classes/debug/com/scalebun/rn/engage/ScaleBunEngageModule.class +0 -0
  376. package/android/build/tmp/kotlin-classes/debug/com/scalebun/rn/engage/ScaleBunEngagePackage.class +0 -0
  377. package/android/build/tmp/kotlin-classes/debug/com/scalebun/rn/engage/ScaleBunNotificationPresenter.class +0 -0
  378. package/android/build/tmp/kotlin-classes/debug/com/scalebun/rn/ota/ScaleBunOtaModule$Companion.class +0 -0
  379. package/android/build/tmp/kotlin-classes/debug/com/scalebun/rn/ota/ScaleBunOtaModule.class +0 -0
  380. package/android/build/tmp/kotlin-classes/debug/com/scalebun/rn/ota/ScaleBunOtaSpec.class +0 -0
  381. package/android/build/tmp/kotlin-classes/debug/com/scalebun/rn/ota/SlotManager$Companion.class +0 -0
  382. package/android/build/tmp/kotlin-classes/debug/com/scalebun/rn/ota/SlotManager.class +0 -0
  383. package/android/build/tmp/kotlin-classes/debug/com/scalebun/rn/performance/PerformanceModule$Companion.class +0 -0
  384. package/android/build/tmp/kotlin-classes/debug/com/scalebun/rn/performance/PerformanceModule$coreListener$1.class +0 -0
  385. package/android/build/tmp/kotlin-classes/debug/com/scalebun/rn/performance/PerformanceModule.class +0 -0
  386. package/android/build/tmp/kotlin-classes/debug/com/scalebun/rn/performance/PerformanceSpec.class +0 -0
  387. package/android/build/tmp/kotlin-classes/debug/com/scalebun/rn/referrer/ScaleBunInstallReferrerModule$Companion.class +0 -0
  388. package/android/build/tmp/kotlin-classes/debug/com/scalebun/rn/referrer/ScaleBunInstallReferrerModule$getInstallReferrer$1.class +0 -0
  389. package/android/build/tmp/kotlin-classes/debug/com/scalebun/rn/referrer/ScaleBunInstallReferrerModule.class +0 -0
  390. package/android/build/tmp/kotlin-classes/debug/com/scalebun/rn/referrer/ScaleBunInstallReferrerSpec.class +0 -0
  391. package/android/build/tmp/kotlin-classes/debug/com/scalebun/rn/storage/ScaleBunStorageModule$Companion.class +0 -0
  392. package/android/build/tmp/kotlin-classes/debug/com/scalebun/rn/storage/ScaleBunStorageModule.class +0 -0
  393. package/android/build/tmp/kotlin-classes/debug/com/scalebun/rn/storage/ScaleBunStorageSpec.class +0 -0
  394. package/android/build/tmp/kotlin-classes/debug/com/scalebun/storage/KvFileStore$Companion.class +0 -0
  395. package/android/build/tmp/kotlin-classes/debug/com/scalebun/storage/KvFileStore.class +0 -0
  396. package/android/build.gradle +86 -86
  397. package/android/consumer-rules.pro +28 -28
  398. package/android/src/main/AndroidManifest.xml +14 -14
  399. package/android/src/main/java/com/scalebun/core/crash/CrashStorage.kt +41 -41
  400. package/android/src/main/java/com/scalebun/core/crash/NativeCrashHandler.kt +79 -79
  401. package/android/src/main/java/com/scalebun/core/performance/ANRWatchdog.kt +100 -100
  402. package/android/src/main/java/com/scalebun/core/performance/AppStartCollector.kt +132 -132
  403. package/android/src/main/java/com/scalebun/core/performance/FrameMetricsCollector.kt +230 -230
  404. package/android/src/main/java/com/scalebun/core/performance/PerformanceCore.kt +165 -165
  405. package/android/src/main/java/com/scalebun/profiler/ProfilerModule.kt +398 -398
  406. package/android/src/main/java/com/scalebun/profiler/ProfilerPackage.kt +24 -24
  407. package/android/src/main/java/com/scalebun/profiler/collectors/CpuCollector.kt +161 -161
  408. package/android/src/main/java/com/scalebun/profiler/collectors/IncidentDetector.kt +223 -223
  409. package/android/src/main/java/com/scalebun/profiler/collectors/MemoryCollector.kt +157 -157
  410. package/android/src/main/java/com/scalebun/profiler/collectors/RenderCollector.kt +194 -194
  411. package/android/src/main/java/com/scalebun/profiler/collectors/SamplerScheduler.kt +218 -218
  412. package/android/src/main/java/com/scalebun/profiler/collectors/ThreadCollector.kt +142 -142
  413. package/android/src/main/java/com/scalebun/replaysdk/ReplaySdkModule.kt +966 -966
  414. package/android/src/main/java/com/scalebun/replaysdk/ReplaySdkPackage.kt +24 -24
  415. package/android/src/main/java/com/scalebun/replaysdk/capture/CaptureReason.kt +47 -47
  416. package/android/src/main/java/com/scalebun/replaysdk/capture/FrameCaptureManager.kt +508 -508
  417. package/android/src/main/java/com/scalebun/replaysdk/capture/FrameCaptureScheduler.kt +187 -187
  418. package/android/src/main/java/com/scalebun/replaysdk/capture/UiStabilityDetector.kt +214 -214
  419. package/android/src/main/java/com/scalebun/replaysdk/core/ReplayConfig.kt +144 -144
  420. package/android/src/main/java/com/scalebun/replaysdk/core/ReplayLogger.kt +31 -31
  421. package/android/src/main/java/com/scalebun/replaysdk/core/SessionIdGenerator.kt +15 -15
  422. package/android/src/main/java/com/scalebun/replaysdk/models/ReplayModels.kt +88 -88
  423. package/android/src/main/java/com/scalebun/replaysdk/outbox/NativeOutbox.kt +541 -541
  424. package/android/src/main/java/com/scalebun/replaysdk/outbox/OutboxUploader.kt +407 -407
  425. package/android/src/main/java/com/scalebun/replaysdk/privacy/PrivacyMaskProcessor.kt +126 -126
  426. package/android/src/main/java/com/scalebun/replaysdk/session/SessionManager.kt +281 -281
  427. package/android/src/main/java/com/scalebun/replaysdk/storage/ReplayStorage.kt +136 -136
  428. package/android/src/main/java/com/scalebun/replaysdk/timeline/TimelineCollector.kt +28 -28
  429. package/android/src/main/java/com/scalebun/replaysdk/tracking/InteractionTracker.kt +419 -419
  430. package/android/src/main/java/com/scalebun/replaysdk/tracking/ScreenTracker.kt +20 -20
  431. package/android/src/main/java/com/scalebun/replaysdk/transport/ReplayTransport.kt +99 -99
  432. package/android/src/main/java/com/scalebun/replaysdk/voice/VoiceRecorder.kt +121 -121
  433. package/android/src/main/java/com/scalebun/replaysdk/voice/VoiceTranscriber.kt +104 -104
  434. package/android/src/main/java/com/scalebun/rn/ScaleBunPackage.kt +113 -113
  435. package/android/src/main/java/com/scalebun/rn/crash/ScaleBunCrashModule.kt +100 -100
  436. package/android/src/main/java/com/scalebun/rn/crash/ScaleBunCrashPackage.kt +22 -22
  437. package/android/src/main/java/com/scalebun/rn/engage/ScaleBunEngageModule.kt +579 -579
  438. package/android/src/main/java/com/scalebun/rn/engage/ScaleBunEngagePackage.kt +22 -22
  439. package/android/src/main/java/com/scalebun/rn/engage/ScaleBunNotificationPresenter.kt +110 -110
  440. package/android/src/main/java/com/scalebun/rn/ota/ScaleBunOtaModule.kt +136 -136
  441. package/android/src/main/java/com/scalebun/rn/ota/SlotManager.kt +285 -285
  442. package/android/src/main/java/com/scalebun/rn/performance/PerformanceModule.kt +206 -206
  443. package/android/src/main/java/com/scalebun/rn/referrer/ScaleBunInstallReferrerModule.kt +77 -77
  444. package/android/src/main/java/com/scalebun/rn/storage/ScaleBunStorageModule.kt +68 -68
  445. package/android/src/main/java/com/scalebun/storage/KvFileStore.kt +174 -174
  446. package/android/src/newarch/java/com/scalebun/profiler/ProfilerSpec.kt +12 -12
  447. package/android/src/newarch/java/com/scalebun/replaysdk/ReplaySdkSpec.kt +12 -12
  448. package/android/src/newarch/java/com/scalebun/rn/crash/ScaleBunCrashSpec.kt +15 -15
  449. package/android/src/newarch/java/com/scalebun/rn/ota/ScaleBunOtaSpec.kt +16 -16
  450. package/android/src/newarch/java/com/scalebun/rn/performance/PerformanceSpec.kt +12 -12
  451. package/android/src/newarch/java/com/scalebun/rn/referrer/ScaleBunInstallReferrerSpec.kt +14 -14
  452. package/android/src/newarch/java/com/scalebun/rn/storage/ScaleBunStorageSpec.kt +16 -16
  453. package/android/src/oldarch/java/com/scalebun/profiler/ProfilerSpec.kt +34 -34
  454. package/android/src/oldarch/java/com/scalebun/replaysdk/ReplaySdkSpec.kt +76 -76
  455. package/android/src/oldarch/java/com/scalebun/rn/crash/ScaleBunCrashSpec.kt +21 -21
  456. package/android/src/oldarch/java/com/scalebun/rn/ota/ScaleBunOtaSpec.kt +25 -25
  457. package/android/src/oldarch/java/com/scalebun/rn/performance/PerformanceSpec.kt +27 -27
  458. package/android/src/oldarch/java/com/scalebun/rn/referrer/ScaleBunInstallReferrerSpec.kt +18 -18
  459. package/android/src/oldarch/java/com/scalebun/rn/storage/ScaleBunStorageSpec.kt +26 -26
  460. package/bin/lib/iosCodemod.js +266 -266
  461. package/bin/scalebun.js +640 -640
  462. package/ios/Capture/InteractionTracker.swift +191 -191
  463. package/ios/Capture/PrivacyMaskProcessor.swift +158 -158
  464. package/ios/Capture/ScreenshotCaptureManager.swift +315 -315
  465. package/ios/Capture/WindowResolver.swift +63 -63
  466. package/ios/Core/ReplayConfig.swift +100 -100
  467. package/ios/Core/ReplayLogger.swift +22 -22
  468. package/ios/Core/SessionIdGenerator.swift +18 -18
  469. package/ios/Crash/ScaleBunCrashBridge.mm +63 -63
  470. package/ios/Crash/ScaleBunCrashHandler.swift +67 -67
  471. package/ios/Crash/ScaleBunCrashModule.swift +69 -69
  472. package/ios/Crash/ScaleBunCrashSignalBridge.h +18 -18
  473. package/ios/Crash/ScaleBunCrashSignalBridge.m +131 -131
  474. package/ios/Crash/ScaleBunCrashStorage.swift +46 -46
  475. package/ios/Engage/ScaleBunEngageBridge.m +32 -32
  476. package/ios/Engage/ScaleBunEngageModule.swift +250 -250
  477. package/ios/Engage/ScaleBunPushNotificationCenter.swift +185 -185
  478. package/ios/Ota/OtaSlotManager.swift +264 -264
  479. package/ios/Ota/ScaleBunOtaBridge.mm +68 -68
  480. package/ios/Ota/ScaleBunOtaModule.swift +123 -123
  481. package/ios/Outbox/NativeOutbox.swift +598 -598
  482. package/ios/Outbox/OutboxUploader.swift +431 -431
  483. package/ios/Performance/ScaleBunPerformanceBridge.m +32 -32
  484. package/ios/Performance/ScaleBunPerformanceModule.swift +290 -290
  485. package/ios/PrivacyInfo.xcprivacy +97 -97
  486. package/ios/Profiler/ScaleBunProfilerBridge.m +55 -55
  487. package/ios/Profiler/ScaleBunProfilerModule.swift +972 -972
  488. package/ios/ReplaySdk-Bridging-Header.h +2 -2
  489. package/ios/ReplaySdk.swift +608 -608
  490. package/ios/ReplaySdkBridge.m +94 -94
  491. package/ios/Session/SessionManager.swift +203 -203
  492. package/ios/Skan/ScaleBunSkanBridge.m +14 -14
  493. package/ios/Skan/ScaleBunSkanModule.swift +61 -61
  494. package/ios/Storage/ReplayStorage.swift +61 -61
  495. package/ios/Storage/ScaleBunKvFileStore.swift +125 -125
  496. package/ios/Storage/ScaleBunStorageBridge.mm +72 -72
  497. package/ios/Storage/ScaleBunStorageModule.swift +57 -57
  498. package/ios/Transport/ReplayTransport.swift +70 -70
  499. package/ios/VoiceRecorder.swift +145 -145
  500. package/lib/commonjs/analytics/EventTracker.js +34 -34
  501. package/lib/commonjs/analytics/EventTracker.js.map +1 -1
  502. package/lib/commonjs/analytics/automaticEvents.js +7 -7
  503. package/lib/commonjs/analytics/automaticEvents.js.map +1 -1
  504. package/lib/commonjs/analytics/batching.js +24 -24
  505. package/lib/commonjs/analytics/batching.js.map +1 -1
  506. package/lib/commonjs/analytics/eventLane.js +13 -13
  507. package/lib/commonjs/analytics/eventLane.js.map +1 -1
  508. package/lib/commonjs/bootstrap/FeatureRegistry.js +17 -17
  509. package/lib/commonjs/bootstrap/FeatureRegistry.js.map +1 -1
  510. package/lib/commonjs/bootstrap/SDKBootstrapper.js +42 -42
  511. package/lib/commonjs/bootstrap/SDKBootstrapper.js.map +1 -1
  512. package/lib/commonjs/bucketing/fnv1a32.js +10 -10
  513. package/lib/commonjs/bucketing/fnv1a32.js.map +1 -1
  514. package/lib/commonjs/compat/codepush.js +6 -6
  515. package/lib/commonjs/compat/codepush.js.map +1 -1
  516. package/lib/commonjs/config/ConfigManager.js +20 -20
  517. package/lib/commonjs/config/ConfigManager.js.map +1 -1
  518. package/lib/commonjs/config/configTypes.js.map +1 -1
  519. package/lib/commonjs/core/architecture.js +23 -23
  520. package/lib/commonjs/core/architecture.js.map +1 -1
  521. package/lib/commonjs/core/clock/now.js +2 -2
  522. package/lib/commonjs/core/clock/now.js.map +1 -1
  523. package/lib/commonjs/core/config/defaults.js.map +1 -1
  524. package/lib/commonjs/core/config/schema.js +102 -102
  525. package/lib/commonjs/core/config/schema.js.map +1 -1
  526. package/lib/commonjs/core/constants/endpoints.js +7 -7
  527. package/lib/commonjs/core/constants/endpoints.js.map +1 -1
  528. package/lib/commonjs/core/constants/timings.js +5 -5
  529. package/lib/commonjs/core/constants/timings.js.map +1 -1
  530. package/lib/commonjs/core/constants/version.js +4 -4
  531. package/lib/commonjs/core/constants/version.js.map +1 -1
  532. package/lib/commonjs/core/context/app.js.map +1 -1
  533. package/lib/commonjs/core/context/device.js.map +1 -1
  534. package/lib/commonjs/core/context/session.js.map +1 -1
  535. package/lib/commonjs/core/context/user.js.map +1 -1
  536. package/lib/commonjs/core/contracts/IFeature.js.map +1 -1
  537. package/lib/commonjs/core/di/container.js.map +1 -1
  538. package/lib/commonjs/core/encoding/base64.js +9 -9
  539. package/lib/commonjs/core/encoding/base64.js.map +1 -1
  540. package/lib/commonjs/core/id/deviceId.js +4 -4
  541. package/lib/commonjs/core/id/deviceId.js.map +1 -1
  542. package/lib/commonjs/core/id/sessionId.js.map +1 -1
  543. package/lib/commonjs/core/lifecycle/appLifecycle.js.map +1 -1
  544. package/lib/commonjs/core/lifecycle/crashSafe.js +3 -3
  545. package/lib/commonjs/core/lifecycle/crashSafe.js.map +1 -1
  546. package/lib/commonjs/core/logger/errorClassification.js +30 -30
  547. package/lib/commonjs/core/logger/errorClassification.js.map +1 -1
  548. package/lib/commonjs/core/logger/internalLogger.js.map +1 -1
  549. package/lib/commonjs/core/logger/levels.js.map +1 -1
  550. package/lib/commonjs/crypto/hmacSha256.js +6 -6
  551. package/lib/commonjs/crypto/hmacSha256.js.map +1 -1
  552. package/lib/commonjs/debug/bootstrap.js +26 -26
  553. package/lib/commonjs/debug/bootstrap.js.map +1 -1
  554. package/lib/commonjs/debug/commands.js +10 -10
  555. package/lib/commonjs/debug/commands.js.map +1 -1
  556. package/lib/commonjs/debug/configBuilder.js +6 -6
  557. package/lib/commonjs/debug/configBuilder.js.map +1 -1
  558. package/lib/commonjs/debug/exportBridge.js +17 -17
  559. package/lib/commonjs/debug/exportBridge.js.map +1 -1
  560. package/lib/commonjs/debug/hostResolver.js +10 -10
  561. package/lib/commonjs/debug/hostResolver.js.map +1 -1
  562. package/lib/commonjs/debug/index.js.map +1 -1
  563. package/lib/commonjs/debug/metrics.js.map +1 -1
  564. package/lib/commonjs/debug/perf.js +11 -11
  565. package/lib/commonjs/debug/perf.js.map +1 -1
  566. package/lib/commonjs/debug/perfWiring.js +10 -10
  567. package/lib/commonjs/debug/perfWiring.js.map +1 -1
  568. package/lib/commonjs/debug/protocol.js.map +1 -1
  569. package/lib/commonjs/debug/redaction.js +26 -26
  570. package/lib/commonjs/debug/redaction.js.map +1 -1
  571. package/lib/commonjs/debug/replayWiring.js +11 -11
  572. package/lib/commonjs/debug/replayWiring.js.map +1 -1
  573. package/lib/commonjs/debug/screenTracking.js +7 -7
  574. package/lib/commonjs/debug/screenTracking.js.map +1 -1
  575. package/lib/commonjs/debug/sessionWiring.js +8 -8
  576. package/lib/commonjs/debug/sessionWiring.js.map +1 -1
  577. package/lib/commonjs/debug/stream.js +26 -26
  578. package/lib/commonjs/debug/stream.js.map +1 -1
  579. package/lib/commonjs/debug/transport.js +24 -24
  580. package/lib/commonjs/debug/transport.js.map +1 -1
  581. package/lib/commonjs/features/bugreport/index.js.map +1 -1
  582. package/lib/commonjs/features/crash/CrashFeature.js +9 -9
  583. package/lib/commonjs/features/crash/CrashFeature.js.map +1 -1
  584. package/lib/commonjs/features/crash/CrashReporter.js +28 -28
  585. package/lib/commonjs/features/crash/CrashReporter.js.map +1 -1
  586. package/lib/commonjs/features/crash/NativeCrashFeature.js +7 -7
  587. package/lib/commonjs/features/crash/NativeCrashFeature.js.map +1 -1
  588. package/lib/commonjs/features/crash/capture.js.map +1 -1
  589. package/lib/commonjs/features/crash/globalHandler.js +11 -11
  590. package/lib/commonjs/features/crash/globalHandler.js.map +1 -1
  591. package/lib/commonjs/features/crash/index.js.map +1 -1
  592. package/lib/commonjs/features/crash/nativeCrashBridge.js +19 -19
  593. package/lib/commonjs/features/crash/nativeCrashBridge.js.map +1 -1
  594. package/lib/commonjs/features/engage/EngageAnchor.js +3 -3
  595. package/lib/commonjs/features/engage/EngageAnchor.js.map +1 -1
  596. package/lib/commonjs/features/engage/EngageArchetypeRenderers.js +19 -19
  597. package/lib/commonjs/features/engage/EngageArchetypeRenderers.js.map +1 -1
  598. package/lib/commonjs/features/engage/EngageInAppView.js +35 -35
  599. package/lib/commonjs/features/engage/EngageInAppView.js.map +1 -1
  600. package/lib/commonjs/features/engage/EngageInlinePlacement.js +7 -7
  601. package/lib/commonjs/features/engage/EngageInlinePlacement.js.map +1 -1
  602. package/lib/commonjs/features/engage/EngagePromptProvider.js +84 -84
  603. package/lib/commonjs/features/engage/EngagePromptProvider.js.map +1 -1
  604. package/lib/commonjs/features/engage/EngagePromptView.js +18 -18
  605. package/lib/commonjs/features/engage/EngagePromptView.js.map +1 -1
  606. package/lib/commonjs/features/engage/EngageTransport.js +79 -79
  607. package/lib/commonjs/features/engage/EngageTransport.js.map +1 -1
  608. package/lib/commonjs/features/engage/EngageVariantContent.js +10 -10
  609. package/lib/commonjs/features/engage/EngageVariantContent.js.map +1 -1
  610. package/lib/commonjs/features/engage/__test-support__/reactNativeStub.js +7 -7
  611. package/lib/commonjs/features/engage/__test-support__/reactNativeStub.js.map +1 -1
  612. package/lib/commonjs/features/engage/attachmentCapture.js +12 -12
  613. package/lib/commonjs/features/engage/attachmentCapture.js.map +1 -1
  614. package/lib/commonjs/features/engage/captureVoiceAttachment.js +20 -20
  615. package/lib/commonjs/features/engage/captureVoiceAttachment.js.map +1 -1
  616. package/lib/commonjs/features/engage/engageCoachmarkTour.js +4 -4
  617. package/lib/commonjs/features/engage/engageCoachmarkTour.js.map +1 -1
  618. package/lib/commonjs/features/engage/engageGameLogic.js.map +1 -1
  619. package/lib/commonjs/features/engage/engageMediaSizing.js +15 -15
  620. package/lib/commonjs/features/engage/engageMediaSizing.js.map +1 -1
  621. package/lib/commonjs/features/engage/engageMultiStepSheet.js +6 -6
  622. package/lib/commonjs/features/engage/engageMultiStepSheet.js.map +1 -1
  623. package/lib/commonjs/features/engage/engageOutcome.js +6 -6
  624. package/lib/commonjs/features/engage/engageOutcome.js.map +1 -1
  625. package/lib/commonjs/features/engage/engagePushTokenBridge.js +20 -20
  626. package/lib/commonjs/features/engage/engagePushTokenBridge.js.map +1 -1
  627. package/lib/commonjs/features/engage/engageShakeBridge.js +16 -16
  628. package/lib/commonjs/features/engage/engageShakeBridge.js.map +1 -1
  629. package/lib/commonjs/features/engage/engageSignals.js.map +1 -1
  630. package/lib/commonjs/features/engage/engageStoreReviewBridge.js +19 -19
  631. package/lib/commonjs/features/engage/engageStoreReviewBridge.js.map +1 -1
  632. package/lib/commonjs/features/engage/engageTestSeenStore.js +29 -29
  633. package/lib/commonjs/features/engage/engageTestSeenStore.js.map +1 -1
  634. package/lib/commonjs/features/engage/engageThrottle.js +76 -76
  635. package/lib/commonjs/features/engage/engageThrottle.js.map +1 -1
  636. package/lib/commonjs/features/engage/engageTriggerEngine.js +7 -7
  637. package/lib/commonjs/features/engage/engageTriggerEngine.js.map +1 -1
  638. package/lib/commonjs/features/engage/engageTypes.js +33 -33
  639. package/lib/commonjs/features/engage/engageTypes.js.map +1 -1
  640. package/lib/commonjs/features/engage/engageVariantResolver.js +13 -13
  641. package/lib/commonjs/features/engage/engageVariantResolver.js.map +1 -1
  642. package/lib/commonjs/features/engage/engageWindowInsets.js +10 -10
  643. package/lib/commonjs/features/engage/engageWindowInsets.js.map +1 -1
  644. package/lib/commonjs/features/engage/gestureTriggerDetector.js.map +1 -1
  645. package/lib/commonjs/features/engage/transcription/TranscriptionProvider.js +16 -16
  646. package/lib/commonjs/features/engage/transcription/TranscriptionProvider.js.map +1 -1
  647. package/lib/commonjs/features/install-referrer/installReferrer.js +26 -26
  648. package/lib/commonjs/features/install-referrer/installReferrer.js.map +1 -1
  649. package/lib/commonjs/features/journey/ScaleBunDebugRoot.js +28 -28
  650. package/lib/commonjs/features/journey/ScaleBunDebugRoot.js.map +1 -1
  651. package/lib/commonjs/features/journey/ScaleBunFlatList.js +15 -15
  652. package/lib/commonjs/features/journey/ScaleBunFlatList.js.map +1 -1
  653. package/lib/commonjs/features/journey/ScaleBunImpression.js +22 -22
  654. package/lib/commonjs/features/journey/ScaleBunImpression.js.map +1 -1
  655. package/lib/commonjs/features/journey/ScaleBunScrollView.js +20 -20
  656. package/lib/commonjs/features/journey/ScaleBunScrollView.js.map +1 -1
  657. package/lib/commonjs/features/journey/ScaleBunSectionList.js +15 -15
  658. package/lib/commonjs/features/journey/ScaleBunSectionList.js.map +1 -1
  659. package/lib/commonjs/features/journey/calibrationContext.js +12 -12
  660. package/lib/commonjs/features/journey/calibrationContext.js.map +1 -1
  661. package/lib/commonjs/features/journey/gestureBuffer.js +9 -9
  662. package/lib/commonjs/features/journey/gestureBuffer.js.map +1 -1
  663. package/lib/commonjs/features/journey/gestureDetector.js +10 -10
  664. package/lib/commonjs/features/journey/gestureDetector.js.map +1 -1
  665. package/lib/commonjs/features/journey/impression.js +18 -18
  666. package/lib/commonjs/features/journey/impression.js.map +1 -1
  667. package/lib/commonjs/features/journey/journeyManager.js +6 -6
  668. package/lib/commonjs/features/journey/journeyManager.js.map +1 -1
  669. package/lib/commonjs/features/journey/journeyTypes.js +5 -5
  670. package/lib/commonjs/features/journey/journeyTypes.js.map +1 -1
  671. package/lib/commonjs/features/journey/navDetector.js +7 -7
  672. package/lib/commonjs/features/journey/navDetector.js.map +1 -1
  673. package/lib/commonjs/features/journey/screenshotHelper.js +7 -7
  674. package/lib/commonjs/features/journey/screenshotHelper.js.map +1 -1
  675. package/lib/commonjs/features/journey/targetRegistry.js +17 -17
  676. package/lib/commonjs/features/journey/targetRegistry.js.map +1 -1
  677. package/lib/commonjs/features/journey/touchTarget.js +29 -29
  678. package/lib/commonjs/features/journey/touchTarget.js.map +1 -1
  679. package/lib/commonjs/features/navigation/AutoScreenDetector.js +61 -61
  680. package/lib/commonjs/features/navigation/AutoScreenDetector.js.map +1 -1
  681. package/lib/commonjs/features/network/NetworkFeature.js +23 -23
  682. package/lib/commonjs/features/network/NetworkFeature.js.map +1 -1
  683. package/lib/commonjs/features/network/index.js +5 -5
  684. package/lib/commonjs/features/network/index.js.map +1 -1
  685. package/lib/commonjs/features/ota/OtaEventEmitter.js +21 -21
  686. package/lib/commonjs/features/ota/OtaEventEmitter.js.map +1 -1
  687. package/lib/commonjs/features/ota/OtaOrchestrator.js +20 -20
  688. package/lib/commonjs/features/ota/OtaOrchestrator.js.map +1 -1
  689. package/lib/commonjs/features/ota/OtaTypes.js.map +1 -1
  690. package/lib/commonjs/features/ota/useOtaUpdate.js +15 -15
  691. package/lib/commonjs/features/ota/useOtaUpdate.js.map +1 -1
  692. package/lib/commonjs/features/performance/PerformanceFeature.js +26 -26
  693. package/lib/commonjs/features/performance/PerformanceFeature.js.map +1 -1
  694. package/lib/commonjs/features/performance/collectors/AppLaunchCollector.js +13 -13
  695. package/lib/commonjs/features/performance/collectors/AppLaunchCollector.js.map +1 -1
  696. package/lib/commonjs/features/performance/collectors/AutoScreenLoadCollector.js +32 -32
  697. package/lib/commonjs/features/performance/collectors/AutoScreenLoadCollector.js.map +1 -1
  698. package/lib/commonjs/features/performance/collectors/CustomTraceCollector.js +13 -13
  699. package/lib/commonjs/features/performance/collectors/CustomTraceCollector.js.map +1 -1
  700. package/lib/commonjs/features/performance/collectors/FrameMetricsCollector.js +11 -11
  701. package/lib/commonjs/features/performance/collectors/FrameMetricsCollector.js.map +1 -1
  702. package/lib/commonjs/features/performance/collectors/JsStallCollector.js +12 -12
  703. package/lib/commonjs/features/performance/collectors/JsStallCollector.js.map +1 -1
  704. package/lib/commonjs/features/performance/collectors/NetworkPerfCollector.js +10 -10
  705. package/lib/commonjs/features/performance/collectors/NetworkPerfCollector.js.map +1 -1
  706. package/lib/commonjs/features/performance/collectors/ScreenLoadCollector.js +11 -11
  707. package/lib/commonjs/features/performance/collectors/ScreenLoadCollector.js.map +1 -1
  708. package/lib/commonjs/features/performance/collectors/UiHangCollector.js +5 -5
  709. package/lib/commonjs/features/performance/collectors/UiHangCollector.js.map +1 -1
  710. package/lib/commonjs/features/performance/config.js +11 -11
  711. package/lib/commonjs/features/performance/config.js.map +1 -1
  712. package/lib/commonjs/features/performance/getNativePerformanceModule.js +11 -11
  713. package/lib/commonjs/features/performance/getNativePerformanceModule.js.map +1 -1
  714. package/lib/commonjs/features/performance/index.js.map +1 -1
  715. package/lib/commonjs/features/performance/metrics/MetricsEngine.js +13 -13
  716. package/lib/commonjs/features/performance/metrics/MetricsEngine.js.map +1 -1
  717. package/lib/commonjs/features/performance/models.js +8 -8
  718. package/lib/commonjs/features/performance/models.js.map +1 -1
  719. package/lib/commonjs/features/performance/transport/PerformanceTransport.js +6 -6
  720. package/lib/commonjs/features/performance/transport/PerformanceTransport.js.map +1 -1
  721. package/lib/commonjs/features/profiler/ProfilerFeature.js +53 -53
  722. package/lib/commonjs/features/profiler/ProfilerFeature.js.map +1 -1
  723. package/lib/commonjs/features/profiler/config.js +15 -15
  724. package/lib/commonjs/features/profiler/config.js.map +1 -1
  725. package/lib/commonjs/features/profiler/contracts.js +22 -22
  726. package/lib/commonjs/features/profiler/contracts.js.map +1 -1
  727. package/lib/commonjs/features/profiler/index.js.map +1 -1
  728. package/lib/commonjs/features/profiler/models.js +44 -44
  729. package/lib/commonjs/features/profiler/models.js.map +1 -1
  730. package/lib/commonjs/features/profiler/transport/ProfilerTransport.js +9 -9
  731. package/lib/commonjs/features/profiler/transport/ProfilerTransport.js.map +1 -1
  732. package/lib/commonjs/features/replay/bridge/adapters/bridgeAdapter.js +17 -17
  733. package/lib/commonjs/features/replay/bridge/adapters/bridgeAdapter.js.map +1 -1
  734. package/lib/commonjs/features/replay/bridge/eventEmitter.js +8 -8
  735. package/lib/commonjs/features/replay/bridge/eventEmitter.js.map +1 -1
  736. package/lib/commonjs/features/replay/bridge/nativeModule.js +20 -20
  737. package/lib/commonjs/features/replay/bridge/nativeModule.js.map +1 -1
  738. package/lib/commonjs/features/replay/core/clock/clock.js +6 -6
  739. package/lib/commonjs/features/replay/core/clock/clock.js.map +1 -1
  740. package/lib/commonjs/features/replay/core/config/defaults.js +2 -2
  741. package/lib/commonjs/features/replay/core/config/defaults.js.map +1 -1
  742. package/lib/commonjs/features/replay/core/config/validator.js +5 -5
  743. package/lib/commonjs/features/replay/core/config/validator.js.map +1 -1
  744. package/lib/commonjs/features/replay/core/env/environmentDetector.js +10 -10
  745. package/lib/commonjs/features/replay/core/env/environmentDetector.js.map +1 -1
  746. package/lib/commonjs/features/replay/core/errors/safeCall.js +4 -4
  747. package/lib/commonjs/features/replay/core/errors/safeCall.js.map +1 -1
  748. package/lib/commonjs/features/replay/core/ids/sessionId.js +5 -5
  749. package/lib/commonjs/features/replay/core/ids/sessionId.js.map +1 -1
  750. package/lib/commonjs/features/replay/core/logger/logger.js +5 -5
  751. package/lib/commonjs/features/replay/core/logger/logger.js.map +1 -1
  752. package/lib/commonjs/features/replay/core/privacy/privacyTypes.js +4 -4
  753. package/lib/commonjs/features/replay/core/privacy/privacyTypes.js.map +1 -1
  754. package/lib/commonjs/features/replay/core/queue/boundedQueue.js +5 -5
  755. package/lib/commonjs/features/replay/core/queue/boundedQueue.js.map +1 -1
  756. package/lib/commonjs/features/replay/integrations/alert/alertInstrumentation.js +59 -59
  757. package/lib/commonjs/features/replay/integrations/alert/alertInstrumentation.js.map +1 -1
  758. package/lib/commonjs/features/replay/integrations/logs/consoleIntegration.js +19 -19
  759. package/lib/commonjs/features/replay/integrations/logs/consoleIntegration.js.map +1 -1
  760. package/lib/commonjs/features/replay/integrations/network/networkAdapter.js +30 -30
  761. package/lib/commonjs/features/replay/integrations/network/networkAdapter.js.map +1 -1
  762. package/lib/commonjs/features/replay/integrations/react-navigation/navigationIntegration.js +19 -19
  763. package/lib/commonjs/features/replay/integrations/react-navigation/navigationIntegration.js.map +1 -1
  764. package/lib/commonjs/features/replay/integrations/touch/ReplayRoot.js +16 -16
  765. package/lib/commonjs/features/replay/integrations/touch/ReplayRoot.js.map +1 -1
  766. package/lib/commonjs/features/replay/pipeline/batching/batchManager.js +5 -5
  767. package/lib/commonjs/features/replay/pipeline/batching/batchManager.js.map +1 -1
  768. package/lib/commonjs/features/replay/pipeline/envelope/envelopeBuilder.js +5 -5
  769. package/lib/commonjs/features/replay/pipeline/envelope/envelopeBuilder.js.map +1 -1
  770. package/lib/commonjs/features/replay/pipeline/retry/retryPolicy.js +4 -4
  771. package/lib/commonjs/features/replay/pipeline/retry/retryPolicy.js.map +1 -1
  772. package/lib/commonjs/features/replay/pipeline/transport/transportTypes.js +7 -7
  773. package/lib/commonjs/features/replay/pipeline/transport/transportTypes.js.map +1 -1
  774. package/lib/commonjs/features/replay/public/api.js +21 -21
  775. package/lib/commonjs/features/replay/public/api.js.map +1 -1
  776. package/lib/commonjs/features/replay/public/enums.js +5 -5
  777. package/lib/commonjs/features/replay/public/enums.js.map +1 -1
  778. package/lib/commonjs/features/replay/public/types.js.map +1 -1
  779. package/lib/commonjs/features/replay/replay/breadcrumbs/breadcrumbCollector.js +5 -5
  780. package/lib/commonjs/features/replay/replay/breadcrumbs/breadcrumbCollector.js.map +1 -1
  781. package/lib/commonjs/features/replay/replay/frames/frameModels.js +4 -4
  782. package/lib/commonjs/features/replay/replay/frames/frameModels.js.map +1 -1
  783. package/lib/commonjs/features/replay/replay/session/sessionOrchestrator.js +10 -10
  784. package/lib/commonjs/features/replay/replay/session/sessionOrchestrator.js.map +1 -1
  785. package/lib/commonjs/features/replay/replay/timeline/timelineModels.js +4 -4
  786. package/lib/commonjs/features/replay/replay/timeline/timelineModels.js.map +1 -1
  787. package/lib/commonjs/features/replay/transport/BackendReplayTransport.js +13 -13
  788. package/lib/commonjs/features/replay/transport/BackendReplayTransport.js.map +1 -1
  789. package/lib/commonjs/features/replay/transport/CompositeReplayTransport.js +8 -8
  790. package/lib/commonjs/features/replay/transport/CompositeReplayTransport.js.map +1 -1
  791. package/lib/commonjs/features/replay/transport/DesktopReplayTransport.js +14 -14
  792. package/lib/commonjs/features/replay/transport/DesktopReplayTransport.js.map +1 -1
  793. package/lib/commonjs/features/replay/transport/ReplayTransport.js.map +1 -1
  794. package/lib/commonjs/features/session/BackendSessionAdapter.js +127 -127
  795. package/lib/commonjs/features/session/BackendSessionAdapter.js.map +1 -1
  796. package/lib/commonjs/features/session/DesktopSessionTransport.js +14 -14
  797. package/lib/commonjs/features/session/DesktopSessionTransport.js.map +1 -1
  798. package/lib/commonjs/features/session/JourneyEventPipeline.js +19 -19
  799. package/lib/commonjs/features/session/JourneyEventPipeline.js.map +1 -1
  800. package/lib/commonjs/features/session/ReplayCaptureManager.js +123 -123
  801. package/lib/commonjs/features/session/ReplayCaptureManager.js.map +1 -1
  802. package/lib/commonjs/features/session/ScrollTracker.js +17 -17
  803. package/lib/commonjs/features/session/ScrollTracker.js.map +1 -1
  804. package/lib/commonjs/features/session/SessionManager.js +143 -143
  805. package/lib/commonjs/features/session/SessionManager.js.map +1 -1
  806. package/lib/commonjs/features/session/SyncDecisionEngine.js +23 -23
  807. package/lib/commonjs/features/session/SyncDecisionEngine.js.map +1 -1
  808. package/lib/commonjs/features/session/index.js.map +1 -1
  809. package/lib/commonjs/features/session/nativeCapture.js +5 -5
  810. package/lib/commonjs/features/session/nativeCapture.js.map +1 -1
  811. package/lib/commonjs/features/session/outboxFrameCapture.js +15 -15
  812. package/lib/commonjs/features/session/outboxFrameCapture.js.map +1 -1
  813. package/lib/commonjs/features/session/sessionTypes.js +44 -44
  814. package/lib/commonjs/features/session/sessionTypes.js.map +1 -1
  815. package/lib/commonjs/features/skan/skanBridge.js +11 -11
  816. package/lib/commonjs/features/skan/skanBridge.js.map +1 -1
  817. package/lib/commonjs/features/skan/skanConversionManager.js +23 -23
  818. package/lib/commonjs/features/skan/skanConversionManager.js.map +1 -1
  819. package/lib/commonjs/index.js.map +1 -1
  820. package/lib/commonjs/integrations/fetch/fetchInterceptor.js +21 -21
  821. package/lib/commonjs/integrations/fetch/fetchInterceptor.js.map +1 -1
  822. package/lib/commonjs/integrations/navigation/screenTracker.js.map +1 -1
  823. package/lib/commonjs/integrations/network/bodyCapture.js +69 -69
  824. package/lib/commonjs/integrations/network/bodyCapture.js.map +1 -1
  825. package/lib/commonjs/integrations/xhr/xhrInterceptor.js +24 -24
  826. package/lib/commonjs/integrations/xhr/xhrInterceptor.js.map +1 -1
  827. package/lib/commonjs/metro/index.js +37 -37
  828. package/lib/commonjs/metro/index.js.map +1 -1
  829. package/lib/commonjs/metro/optionalDependencyStub.js.map +1 -1
  830. package/lib/commonjs/metro/optionalModules.js +16 -16
  831. package/lib/commonjs/metro/optionalModules.js.map +1 -1
  832. package/lib/commonjs/pipeline/dispatcher/dispatcher.js.map +1 -1
  833. package/lib/commonjs/pipeline/envelope/envelope.js.map +1 -1
  834. package/lib/commonjs/pipeline/envelope/serializer.js.map +1 -1
  835. package/lib/commonjs/pipeline/processors/dedupe.js.map +1 -1
  836. package/lib/commonjs/pipeline/processors/enrich.js.map +1 -1
  837. package/lib/commonjs/pipeline/processors/sampling.js.map +1 -1
  838. package/lib/commonjs/pipeline/processors/sanitize.js.map +1 -1
  839. package/lib/commonjs/pipeline/queue/flushQueue.js +4 -4
  840. package/lib/commonjs/pipeline/queue/flushQueue.js.map +1 -1
  841. package/lib/commonjs/pipeline/queue/memoryQueue.js.map +1 -1
  842. package/lib/commonjs/pipeline/queue/persistentQueue.js +80 -80
  843. package/lib/commonjs/pipeline/queue/persistentQueue.js.map +1 -1
  844. package/lib/commonjs/pipeline/queue/queuePolicy.js.map +1 -1
  845. package/lib/commonjs/pipeline/scheduler/flushScheduler.js.map +1 -1
  846. package/lib/commonjs/pipeline/scheduler/retryPolicy.js +2 -2
  847. package/lib/commonjs/pipeline/scheduler/retryPolicy.js.map +1 -1
  848. package/lib/commonjs/public/ScaleBunFacade.js +274 -274
  849. package/lib/commonjs/public/ScaleBunFacade.js.map +1 -1
  850. package/lib/commonjs/public/ScaleBunProvider.js +3 -3
  851. package/lib/commonjs/public/ScaleBunProvider.js.map +1 -1
  852. package/lib/commonjs/public/typedTracker.js +36 -36
  853. package/lib/commonjs/public/typedTracker.js.map +1 -1
  854. package/lib/commonjs/public/types.js.map +1 -1
  855. package/lib/commonjs/push/PushManager.js +21 -21
  856. package/lib/commonjs/push/PushManager.js.map +1 -1
  857. package/lib/commonjs/push/adapters/ManualAdapter.js +14 -14
  858. package/lib/commonjs/push/adapters/ManualAdapter.js.map +1 -1
  859. package/lib/commonjs/push/adapters/NativeBridgeAdapter.js +17 -17
  860. package/lib/commonjs/push/adapters/NativeBridgeAdapter.js.map +1 -1
  861. package/lib/commonjs/push/adapters/NoopAdapter.js +5 -5
  862. package/lib/commonjs/push/adapters/NoopAdapter.js.map +1 -1
  863. package/lib/commonjs/push/adapters/RNFirebaseMessagingAdapter.js +17 -17
  864. package/lib/commonjs/push/adapters/RNFirebaseMessagingAdapter.js.map +1 -1
  865. package/lib/commonjs/push/adapters/loadMessaging.js +12 -12
  866. package/lib/commonjs/push/adapters/loadMessaging.js.map +1 -1
  867. package/lib/commonjs/push/adapters/loadNotifee.js +12 -12
  868. package/lib/commonjs/push/adapters/loadNotifee.js.map +1 -1
  869. package/lib/commonjs/push/adapters/selectAdapter.js +14 -14
  870. package/lib/commonjs/push/adapters/selectAdapter.js.map +1 -1
  871. package/lib/commonjs/push/detect/capabilities.js +19 -19
  872. package/lib/commonjs/push/detect/capabilities.js.map +1 -1
  873. package/lib/commonjs/push/index.js.map +1 -1
  874. package/lib/commonjs/push/native/nativeNotifications.js +32 -32
  875. package/lib/commonjs/push/native/nativeNotifications.js.map +1 -1
  876. package/lib/commonjs/push/types.js.map +1 -1
  877. package/lib/commonjs/specs/NativeReplaySdk.js +18 -18
  878. package/lib/commonjs/specs/NativeReplaySdk.js.map +1 -1
  879. package/lib/commonjs/specs/NativeScaleBunCrash.js +19 -19
  880. package/lib/commonjs/specs/NativeScaleBunCrash.js.map +1 -1
  881. package/lib/commonjs/specs/NativeScaleBunInstallReferrer.js +14 -14
  882. package/lib/commonjs/specs/NativeScaleBunInstallReferrer.js.map +1 -1
  883. package/lib/commonjs/specs/NativeScaleBunOta.js +21 -21
  884. package/lib/commonjs/specs/NativeScaleBunOta.js.map +1 -1
  885. package/lib/commonjs/specs/NativeScaleBunPerformance.js +15 -15
  886. package/lib/commonjs/specs/NativeScaleBunPerformance.js.map +1 -1
  887. package/lib/commonjs/specs/NativeScaleBunProfiler.js +16 -16
  888. package/lib/commonjs/specs/NativeScaleBunProfiler.js.map +1 -1
  889. package/lib/commonjs/specs/NativeScaleBunStorage.js +29 -29
  890. package/lib/commonjs/specs/NativeScaleBunStorage.js.map +1 -1
  891. package/lib/commonjs/storage/StorageBackend.js +83 -83
  892. package/lib/commonjs/storage/StorageBackend.js.map +1 -1
  893. package/lib/commonjs/storage/db/sqlite.js.map +1 -1
  894. package/lib/commonjs/storage/files/fileStore.js.map +1 -1
  895. package/lib/commonjs/transport/auth/sdkSession.js.map +1 -1
  896. package/lib/commonjs/transport/backoff/exponentialJitter.js +2 -2
  897. package/lib/commonjs/transport/backoff/exponentialJitter.js.map +1 -1
  898. package/lib/commonjs/transport/http/endpoints.js.map +1 -1
  899. package/lib/commonjs/transport/http/httpClient.js +3 -3
  900. package/lib/commonjs/transport/http/httpClient.js.map +1 -1
  901. package/lib/commonjs/transport/rateLimit/retryAfter.js.map +1 -1
  902. package/lib/commonjs/transport/signing/requestSigner.js.map +1 -1
  903. package/lib/commonjs/vendor/protocol/index.js +74 -74
  904. package/lib/commonjs/vendor/protocol/index.js.map +1 -1
  905. package/lib/commonjs/vendor/protocol/internal/validation.js +23 -23
  906. package/lib/commonjs/vendor/protocol/internal/validation.js.map +1 -1
  907. package/lib/commonjs/vendor/sdk-contracts/bridge.js.map +1 -1
  908. package/lib/commonjs/vendor/sdk-contracts/config.js.map +1 -1
  909. package/lib/commonjs/vendor/sdk-contracts/events.js.map +1 -1
  910. package/lib/commonjs/vendor/sdk-contracts/features.js.map +1 -1
  911. package/lib/commonjs/vendor/sdk-contracts/index.js.map +1 -1
  912. package/lib/commonjs/vendor/sdk-contracts/platform.js.map +1 -1
  913. package/lib/commonjs/vendor/sdk-contracts/session-boundary.js.map +1 -1
  914. package/lib/commonjs/vendor/sdk-contracts/session.js.map +1 -1
  915. package/lib/commonjs/vendor/vendor.manifest +10 -10
  916. package/lib/module/analytics/EventTracker.js +34 -34
  917. package/lib/module/analytics/EventTracker.js.map +1 -1
  918. package/lib/module/analytics/automaticEvents.js +7 -7
  919. package/lib/module/analytics/automaticEvents.js.map +1 -1
  920. package/lib/module/analytics/batching.js +24 -24
  921. package/lib/module/analytics/batching.js.map +1 -1
  922. package/lib/module/analytics/eventLane.js +13 -13
  923. package/lib/module/analytics/eventLane.js.map +1 -1
  924. package/lib/module/bootstrap/FeatureRegistry.js +17 -17
  925. package/lib/module/bootstrap/FeatureRegistry.js.map +1 -1
  926. package/lib/module/bootstrap/SDKBootstrapper.js +42 -42
  927. package/lib/module/bootstrap/SDKBootstrapper.js.map +1 -1
  928. package/lib/module/bucketing/fnv1a32.js +10 -10
  929. package/lib/module/bucketing/fnv1a32.js.map +1 -1
  930. package/lib/module/compat/codepush.js +6 -6
  931. package/lib/module/compat/codepush.js.map +1 -1
  932. package/lib/module/config/ConfigManager.js +20 -20
  933. package/lib/module/config/ConfigManager.js.map +1 -1
  934. package/lib/module/config/configTypes.js.map +1 -1
  935. package/lib/module/core/architecture.js +23 -23
  936. package/lib/module/core/architecture.js.map +1 -1
  937. package/lib/module/core/clock/now.js +2 -2
  938. package/lib/module/core/clock/now.js.map +1 -1
  939. package/lib/module/core/config/defaults.js.map +1 -1
  940. package/lib/module/core/config/schema.js +102 -102
  941. package/lib/module/core/config/schema.js.map +1 -1
  942. package/lib/module/core/constants/endpoints.js +7 -7
  943. package/lib/module/core/constants/endpoints.js.map +1 -1
  944. package/lib/module/core/constants/timings.js +5 -5
  945. package/lib/module/core/constants/timings.js.map +1 -1
  946. package/lib/module/core/constants/version.js +4 -4
  947. package/lib/module/core/constants/version.js.map +1 -1
  948. package/lib/module/core/context/app.js.map +1 -1
  949. package/lib/module/core/context/device.js.map +1 -1
  950. package/lib/module/core/context/session.js.map +1 -1
  951. package/lib/module/core/context/user.js.map +1 -1
  952. package/lib/module/core/contracts/IFeature.js.map +1 -1
  953. package/lib/module/core/di/container.js.map +1 -1
  954. package/lib/module/core/encoding/base64.js +9 -9
  955. package/lib/module/core/encoding/base64.js.map +1 -1
  956. package/lib/module/core/id/deviceId.js +4 -4
  957. package/lib/module/core/id/deviceId.js.map +1 -1
  958. package/lib/module/core/id/sessionId.js.map +1 -1
  959. package/lib/module/core/lifecycle/appLifecycle.js.map +1 -1
  960. package/lib/module/core/lifecycle/crashSafe.js +3 -3
  961. package/lib/module/core/lifecycle/crashSafe.js.map +1 -1
  962. package/lib/module/core/logger/errorClassification.js +30 -30
  963. package/lib/module/core/logger/errorClassification.js.map +1 -1
  964. package/lib/module/core/logger/internalLogger.js.map +1 -1
  965. package/lib/module/core/logger/levels.js.map +1 -1
  966. package/lib/module/crypto/hmacSha256.js +6 -6
  967. package/lib/module/crypto/hmacSha256.js.map +1 -1
  968. package/lib/module/debug/bootstrap.js +26 -26
  969. package/lib/module/debug/bootstrap.js.map +1 -1
  970. package/lib/module/debug/commands.js +10 -10
  971. package/lib/module/debug/commands.js.map +1 -1
  972. package/lib/module/debug/configBuilder.js +6 -6
  973. package/lib/module/debug/configBuilder.js.map +1 -1
  974. package/lib/module/debug/exportBridge.js +17 -17
  975. package/lib/module/debug/exportBridge.js.map +1 -1
  976. package/lib/module/debug/hostResolver.js +10 -10
  977. package/lib/module/debug/hostResolver.js.map +1 -1
  978. package/lib/module/debug/index.js +5 -5
  979. package/lib/module/debug/index.js.map +1 -1
  980. package/lib/module/debug/metrics.js.map +1 -1
  981. package/lib/module/debug/perf.js +11 -11
  982. package/lib/module/debug/perf.js.map +1 -1
  983. package/lib/module/debug/perfWiring.js +10 -10
  984. package/lib/module/debug/perfWiring.js.map +1 -1
  985. package/lib/module/debug/protocol.js +11 -11
  986. package/lib/module/debug/protocol.js.map +1 -1
  987. package/lib/module/debug/redaction.js +26 -26
  988. package/lib/module/debug/redaction.js.map +1 -1
  989. package/lib/module/debug/replayWiring.js +11 -11
  990. package/lib/module/debug/replayWiring.js.map +1 -1
  991. package/lib/module/debug/screenTracking.js +7 -7
  992. package/lib/module/debug/screenTracking.js.map +1 -1
  993. package/lib/module/debug/sessionWiring.js +8 -8
  994. package/lib/module/debug/sessionWiring.js.map +1 -1
  995. package/lib/module/debug/stream.js +26 -26
  996. package/lib/module/debug/stream.js.map +1 -1
  997. package/lib/module/debug/transport.js +24 -24
  998. package/lib/module/debug/transport.js.map +1 -1
  999. package/lib/module/features/bugreport/index.js.map +1 -1
  1000. package/lib/module/features/crash/CrashFeature.js +9 -9
  1001. package/lib/module/features/crash/CrashFeature.js.map +1 -1
  1002. package/lib/module/features/crash/CrashReporter.js +28 -28
  1003. package/lib/module/features/crash/CrashReporter.js.map +1 -1
  1004. package/lib/module/features/crash/NativeCrashFeature.js +7 -7
  1005. package/lib/module/features/crash/NativeCrashFeature.js.map +1 -1
  1006. package/lib/module/features/crash/capture.js.map +1 -1
  1007. package/lib/module/features/crash/globalHandler.js +11 -11
  1008. package/lib/module/features/crash/globalHandler.js.map +1 -1
  1009. package/lib/module/features/crash/index.js.map +1 -1
  1010. package/lib/module/features/crash/nativeCrashBridge.js +19 -19
  1011. package/lib/module/features/crash/nativeCrashBridge.js.map +1 -1
  1012. package/lib/module/features/engage/EngageAnchor.js +3 -3
  1013. package/lib/module/features/engage/EngageAnchor.js.map +1 -1
  1014. package/lib/module/features/engage/EngageArchetypeRenderers.js +19 -19
  1015. package/lib/module/features/engage/EngageArchetypeRenderers.js.map +1 -1
  1016. package/lib/module/features/engage/EngageInAppView.js +35 -35
  1017. package/lib/module/features/engage/EngageInAppView.js.map +1 -1
  1018. package/lib/module/features/engage/EngageInlinePlacement.js +7 -7
  1019. package/lib/module/features/engage/EngageInlinePlacement.js.map +1 -1
  1020. package/lib/module/features/engage/EngagePromptProvider.js +84 -84
  1021. package/lib/module/features/engage/EngagePromptProvider.js.map +1 -1
  1022. package/lib/module/features/engage/EngagePromptView.js +18 -18
  1023. package/lib/module/features/engage/EngagePromptView.js.map +1 -1
  1024. package/lib/module/features/engage/EngageTransport.js +79 -79
  1025. package/lib/module/features/engage/EngageTransport.js.map +1 -1
  1026. package/lib/module/features/engage/EngageVariantContent.js +10 -10
  1027. package/lib/module/features/engage/EngageVariantContent.js.map +1 -1
  1028. package/lib/module/features/engage/__test-support__/reactNativeStub.js +7 -7
  1029. package/lib/module/features/engage/__test-support__/reactNativeStub.js.map +1 -1
  1030. package/lib/module/features/engage/attachmentCapture.js +12 -12
  1031. package/lib/module/features/engage/attachmentCapture.js.map +1 -1
  1032. package/lib/module/features/engage/captureVoiceAttachment.js +20 -20
  1033. package/lib/module/features/engage/captureVoiceAttachment.js.map +1 -1
  1034. package/lib/module/features/engage/engageCoachmarkTour.js +4 -4
  1035. package/lib/module/features/engage/engageCoachmarkTour.js.map +1 -1
  1036. package/lib/module/features/engage/engageGameLogic.js.map +1 -1
  1037. package/lib/module/features/engage/engageMediaSizing.js +15 -15
  1038. package/lib/module/features/engage/engageMediaSizing.js.map +1 -1
  1039. package/lib/module/features/engage/engageMultiStepSheet.js +6 -6
  1040. package/lib/module/features/engage/engageMultiStepSheet.js.map +1 -1
  1041. package/lib/module/features/engage/engageOutcome.js +6 -6
  1042. package/lib/module/features/engage/engageOutcome.js.map +1 -1
  1043. package/lib/module/features/engage/engagePushTokenBridge.js +20 -20
  1044. package/lib/module/features/engage/engagePushTokenBridge.js.map +1 -1
  1045. package/lib/module/features/engage/engageShakeBridge.js +16 -16
  1046. package/lib/module/features/engage/engageShakeBridge.js.map +1 -1
  1047. package/lib/module/features/engage/engageSignals.js.map +1 -1
  1048. package/lib/module/features/engage/engageStoreReviewBridge.js +19 -19
  1049. package/lib/module/features/engage/engageStoreReviewBridge.js.map +1 -1
  1050. package/lib/module/features/engage/engageTestSeenStore.js +29 -29
  1051. package/lib/module/features/engage/engageTestSeenStore.js.map +1 -1
  1052. package/lib/module/features/engage/engageThrottle.js +76 -76
  1053. package/lib/module/features/engage/engageThrottle.js.map +1 -1
  1054. package/lib/module/features/engage/engageTriggerEngine.js +7 -7
  1055. package/lib/module/features/engage/engageTriggerEngine.js.map +1 -1
  1056. package/lib/module/features/engage/engageTypes.js +33 -33
  1057. package/lib/module/features/engage/engageTypes.js.map +1 -1
  1058. package/lib/module/features/engage/engageVariantResolver.js +13 -13
  1059. package/lib/module/features/engage/engageVariantResolver.js.map +1 -1
  1060. package/lib/module/features/engage/engageWindowInsets.js +10 -10
  1061. package/lib/module/features/engage/engageWindowInsets.js.map +1 -1
  1062. package/lib/module/features/engage/gestureTriggerDetector.js.map +1 -1
  1063. package/lib/module/features/engage/transcription/TranscriptionProvider.js +16 -16
  1064. package/lib/module/features/engage/transcription/TranscriptionProvider.js.map +1 -1
  1065. package/lib/module/features/install-referrer/installReferrer.js +26 -26
  1066. package/lib/module/features/install-referrer/installReferrer.js.map +1 -1
  1067. package/lib/module/features/journey/ScaleBunDebugRoot.js +28 -28
  1068. package/lib/module/features/journey/ScaleBunDebugRoot.js.map +1 -1
  1069. package/lib/module/features/journey/ScaleBunFlatList.js +15 -15
  1070. package/lib/module/features/journey/ScaleBunFlatList.js.map +1 -1
  1071. package/lib/module/features/journey/ScaleBunImpression.js +22 -22
  1072. package/lib/module/features/journey/ScaleBunImpression.js.map +1 -1
  1073. package/lib/module/features/journey/ScaleBunScrollView.js +20 -20
  1074. package/lib/module/features/journey/ScaleBunScrollView.js.map +1 -1
  1075. package/lib/module/features/journey/ScaleBunSectionList.js +15 -15
  1076. package/lib/module/features/journey/ScaleBunSectionList.js.map +1 -1
  1077. package/lib/module/features/journey/calibrationContext.js +12 -12
  1078. package/lib/module/features/journey/calibrationContext.js.map +1 -1
  1079. package/lib/module/features/journey/gestureBuffer.js +9 -9
  1080. package/lib/module/features/journey/gestureBuffer.js.map +1 -1
  1081. package/lib/module/features/journey/gestureDetector.js +10 -10
  1082. package/lib/module/features/journey/gestureDetector.js.map +1 -1
  1083. package/lib/module/features/journey/impression.js +18 -18
  1084. package/lib/module/features/journey/impression.js.map +1 -1
  1085. package/lib/module/features/journey/journeyManager.js +6 -6
  1086. package/lib/module/features/journey/journeyManager.js.map +1 -1
  1087. package/lib/module/features/journey/journeyTypes.js +5 -5
  1088. package/lib/module/features/journey/journeyTypes.js.map +1 -1
  1089. package/lib/module/features/journey/navDetector.js +7 -7
  1090. package/lib/module/features/journey/navDetector.js.map +1 -1
  1091. package/lib/module/features/journey/screenshotHelper.js +7 -7
  1092. package/lib/module/features/journey/screenshotHelper.js.map +1 -1
  1093. package/lib/module/features/journey/targetRegistry.js +17 -17
  1094. package/lib/module/features/journey/targetRegistry.js.map +1 -1
  1095. package/lib/module/features/journey/touchTarget.js +29 -29
  1096. package/lib/module/features/journey/touchTarget.js.map +1 -1
  1097. package/lib/module/features/navigation/AutoScreenDetector.js +61 -61
  1098. package/lib/module/features/navigation/AutoScreenDetector.js.map +1 -1
  1099. package/lib/module/features/network/NetworkFeature.js +23 -23
  1100. package/lib/module/features/network/NetworkFeature.js.map +1 -1
  1101. package/lib/module/features/network/index.js +5 -5
  1102. package/lib/module/features/network/index.js.map +1 -1
  1103. package/lib/module/features/ota/OtaEventEmitter.js +21 -21
  1104. package/lib/module/features/ota/OtaEventEmitter.js.map +1 -1
  1105. package/lib/module/features/ota/OtaOrchestrator.js +20 -20
  1106. package/lib/module/features/ota/OtaOrchestrator.js.map +1 -1
  1107. package/lib/module/features/ota/OtaTypes.js.map +1 -1
  1108. package/lib/module/features/ota/useOtaUpdate.js +15 -15
  1109. package/lib/module/features/ota/useOtaUpdate.js.map +1 -1
  1110. package/lib/module/features/performance/PerformanceFeature.js +26 -26
  1111. package/lib/module/features/performance/PerformanceFeature.js.map +1 -1
  1112. package/lib/module/features/performance/collectors/AppLaunchCollector.js +13 -13
  1113. package/lib/module/features/performance/collectors/AppLaunchCollector.js.map +1 -1
  1114. package/lib/module/features/performance/collectors/AutoScreenLoadCollector.js +32 -32
  1115. package/lib/module/features/performance/collectors/AutoScreenLoadCollector.js.map +1 -1
  1116. package/lib/module/features/performance/collectors/CustomTraceCollector.js +13 -13
  1117. package/lib/module/features/performance/collectors/CustomTraceCollector.js.map +1 -1
  1118. package/lib/module/features/performance/collectors/FrameMetricsCollector.js +11 -11
  1119. package/lib/module/features/performance/collectors/FrameMetricsCollector.js.map +1 -1
  1120. package/lib/module/features/performance/collectors/JsStallCollector.js +12 -12
  1121. package/lib/module/features/performance/collectors/JsStallCollector.js.map +1 -1
  1122. package/lib/module/features/performance/collectors/NetworkPerfCollector.js +10 -10
  1123. package/lib/module/features/performance/collectors/NetworkPerfCollector.js.map +1 -1
  1124. package/lib/module/features/performance/collectors/ScreenLoadCollector.js +11 -11
  1125. package/lib/module/features/performance/collectors/ScreenLoadCollector.js.map +1 -1
  1126. package/lib/module/features/performance/collectors/UiHangCollector.js +5 -5
  1127. package/lib/module/features/performance/collectors/UiHangCollector.js.map +1 -1
  1128. package/lib/module/features/performance/config.js +11 -11
  1129. package/lib/module/features/performance/config.js.map +1 -1
  1130. package/lib/module/features/performance/getNativePerformanceModule.js +11 -11
  1131. package/lib/module/features/performance/getNativePerformanceModule.js.map +1 -1
  1132. package/lib/module/features/performance/index.js +2 -2
  1133. package/lib/module/features/performance/index.js.map +1 -1
  1134. package/lib/module/features/performance/metrics/MetricsEngine.js +13 -13
  1135. package/lib/module/features/performance/metrics/MetricsEngine.js.map +1 -1
  1136. package/lib/module/features/performance/models.js +8 -8
  1137. package/lib/module/features/performance/models.js.map +1 -1
  1138. package/lib/module/features/performance/transport/PerformanceTransport.js +6 -6
  1139. package/lib/module/features/performance/transport/PerformanceTransport.js.map +1 -1
  1140. package/lib/module/features/profiler/ProfilerFeature.js +53 -53
  1141. package/lib/module/features/profiler/ProfilerFeature.js.map +1 -1
  1142. package/lib/module/features/profiler/config.js +15 -15
  1143. package/lib/module/features/profiler/config.js.map +1 -1
  1144. package/lib/module/features/profiler/contracts.js +22 -22
  1145. package/lib/module/features/profiler/contracts.js.map +1 -1
  1146. package/lib/module/features/profiler/index.js +4 -4
  1147. package/lib/module/features/profiler/index.js.map +1 -1
  1148. package/lib/module/features/profiler/models.js +44 -44
  1149. package/lib/module/features/profiler/models.js.map +1 -1
  1150. package/lib/module/features/profiler/transport/ProfilerTransport.js +9 -9
  1151. package/lib/module/features/profiler/transport/ProfilerTransport.js.map +1 -1
  1152. package/lib/module/features/replay/bridge/adapters/bridgeAdapter.js +17 -17
  1153. package/lib/module/features/replay/bridge/adapters/bridgeAdapter.js.map +1 -1
  1154. package/lib/module/features/replay/bridge/eventEmitter.js +8 -8
  1155. package/lib/module/features/replay/bridge/eventEmitter.js.map +1 -1
  1156. package/lib/module/features/replay/bridge/nativeModule.js +20 -20
  1157. package/lib/module/features/replay/bridge/nativeModule.js.map +1 -1
  1158. package/lib/module/features/replay/core/clock/clock.js +6 -6
  1159. package/lib/module/features/replay/core/clock/clock.js.map +1 -1
  1160. package/lib/module/features/replay/core/config/defaults.js +2 -2
  1161. package/lib/module/features/replay/core/config/defaults.js.map +1 -1
  1162. package/lib/module/features/replay/core/config/validator.js +5 -5
  1163. package/lib/module/features/replay/core/config/validator.js.map +1 -1
  1164. package/lib/module/features/replay/core/env/environmentDetector.js +10 -10
  1165. package/lib/module/features/replay/core/env/environmentDetector.js.map +1 -1
  1166. package/lib/module/features/replay/core/errors/safeCall.js +4 -4
  1167. package/lib/module/features/replay/core/errors/safeCall.js.map +1 -1
  1168. package/lib/module/features/replay/core/ids/sessionId.js +5 -5
  1169. package/lib/module/features/replay/core/ids/sessionId.js.map +1 -1
  1170. package/lib/module/features/replay/core/logger/logger.js +5 -5
  1171. package/lib/module/features/replay/core/logger/logger.js.map +1 -1
  1172. package/lib/module/features/replay/core/privacy/privacyTypes.js +4 -4
  1173. package/lib/module/features/replay/core/privacy/privacyTypes.js.map +1 -1
  1174. package/lib/module/features/replay/core/queue/boundedQueue.js +5 -5
  1175. package/lib/module/features/replay/core/queue/boundedQueue.js.map +1 -1
  1176. package/lib/module/features/replay/integrations/alert/alertInstrumentation.js +59 -59
  1177. package/lib/module/features/replay/integrations/alert/alertInstrumentation.js.map +1 -1
  1178. package/lib/module/features/replay/integrations/logs/consoleIntegration.js +19 -19
  1179. package/lib/module/features/replay/integrations/logs/consoleIntegration.js.map +1 -1
  1180. package/lib/module/features/replay/integrations/network/networkAdapter.js +30 -30
  1181. package/lib/module/features/replay/integrations/network/networkAdapter.js.map +1 -1
  1182. package/lib/module/features/replay/integrations/react-navigation/navigationIntegration.js +19 -19
  1183. package/lib/module/features/replay/integrations/react-navigation/navigationIntegration.js.map +1 -1
  1184. package/lib/module/features/replay/integrations/touch/ReplayRoot.js +16 -16
  1185. package/lib/module/features/replay/integrations/touch/ReplayRoot.js.map +1 -1
  1186. package/lib/module/features/replay/pipeline/batching/batchManager.js +5 -5
  1187. package/lib/module/features/replay/pipeline/batching/batchManager.js.map +1 -1
  1188. package/lib/module/features/replay/pipeline/envelope/envelopeBuilder.js +5 -5
  1189. package/lib/module/features/replay/pipeline/envelope/envelopeBuilder.js.map +1 -1
  1190. package/lib/module/features/replay/pipeline/retry/retryPolicy.js +4 -4
  1191. package/lib/module/features/replay/pipeline/retry/retryPolicy.js.map +1 -1
  1192. package/lib/module/features/replay/pipeline/transport/transportTypes.js +7 -7
  1193. package/lib/module/features/replay/pipeline/transport/transportTypes.js.map +1 -1
  1194. package/lib/module/features/replay/public/api.js +21 -21
  1195. package/lib/module/features/replay/public/api.js.map +1 -1
  1196. package/lib/module/features/replay/public/enums.js +5 -5
  1197. package/lib/module/features/replay/public/enums.js.map +1 -1
  1198. package/lib/module/features/replay/public/types.js.map +1 -1
  1199. package/lib/module/features/replay/replay/breadcrumbs/breadcrumbCollector.js +5 -5
  1200. package/lib/module/features/replay/replay/breadcrumbs/breadcrumbCollector.js.map +1 -1
  1201. package/lib/module/features/replay/replay/frames/frameModels.js +4 -4
  1202. package/lib/module/features/replay/replay/frames/frameModels.js.map +1 -1
  1203. package/lib/module/features/replay/replay/session/sessionOrchestrator.js +10 -10
  1204. package/lib/module/features/replay/replay/session/sessionOrchestrator.js.map +1 -1
  1205. package/lib/module/features/replay/replay/timeline/timelineModels.js +4 -4
  1206. package/lib/module/features/replay/replay/timeline/timelineModels.js.map +1 -1
  1207. package/lib/module/features/replay/transport/BackendReplayTransport.js +13 -13
  1208. package/lib/module/features/replay/transport/BackendReplayTransport.js.map +1 -1
  1209. package/lib/module/features/replay/transport/CompositeReplayTransport.js +8 -8
  1210. package/lib/module/features/replay/transport/CompositeReplayTransport.js.map +1 -1
  1211. package/lib/module/features/replay/transport/DesktopReplayTransport.js +14 -14
  1212. package/lib/module/features/replay/transport/DesktopReplayTransport.js.map +1 -1
  1213. package/lib/module/features/replay/transport/ReplayTransport.js.map +1 -1
  1214. package/lib/module/features/session/BackendSessionAdapter.js +127 -127
  1215. package/lib/module/features/session/BackendSessionAdapter.js.map +1 -1
  1216. package/lib/module/features/session/DesktopSessionTransport.js +14 -14
  1217. package/lib/module/features/session/DesktopSessionTransport.js.map +1 -1
  1218. package/lib/module/features/session/JourneyEventPipeline.js +19 -19
  1219. package/lib/module/features/session/JourneyEventPipeline.js.map +1 -1
  1220. package/lib/module/features/session/ReplayCaptureManager.js +123 -123
  1221. package/lib/module/features/session/ReplayCaptureManager.js.map +1 -1
  1222. package/lib/module/features/session/ScrollTracker.js +17 -17
  1223. package/lib/module/features/session/ScrollTracker.js.map +1 -1
  1224. package/lib/module/features/session/SessionManager.js +143 -143
  1225. package/lib/module/features/session/SessionManager.js.map +1 -1
  1226. package/lib/module/features/session/SyncDecisionEngine.js +23 -23
  1227. package/lib/module/features/session/SyncDecisionEngine.js.map +1 -1
  1228. package/lib/module/features/session/index.js +5 -5
  1229. package/lib/module/features/session/index.js.map +1 -1
  1230. package/lib/module/features/session/nativeCapture.js +5 -5
  1231. package/lib/module/features/session/nativeCapture.js.map +1 -1
  1232. package/lib/module/features/session/outboxFrameCapture.js +15 -15
  1233. package/lib/module/features/session/outboxFrameCapture.js.map +1 -1
  1234. package/lib/module/features/session/sessionTypes.js +44 -44
  1235. package/lib/module/features/session/sessionTypes.js.map +1 -1
  1236. package/lib/module/features/skan/skanBridge.js +11 -11
  1237. package/lib/module/features/skan/skanBridge.js.map +1 -1
  1238. package/lib/module/features/skan/skanConversionManager.js +23 -23
  1239. package/lib/module/features/skan/skanConversionManager.js.map +1 -1
  1240. package/lib/module/index.js +10 -10
  1241. package/lib/module/index.js.map +1 -1
  1242. package/lib/module/integrations/fetch/fetchInterceptor.js +21 -21
  1243. package/lib/module/integrations/fetch/fetchInterceptor.js.map +1 -1
  1244. package/lib/module/integrations/navigation/screenTracker.js.map +1 -1
  1245. package/lib/module/integrations/network/bodyCapture.js +69 -69
  1246. package/lib/module/integrations/network/bodyCapture.js.map +1 -1
  1247. package/lib/module/integrations/xhr/xhrInterceptor.js +24 -24
  1248. package/lib/module/integrations/xhr/xhrInterceptor.js.map +1 -1
  1249. package/lib/module/metro/index.js +37 -37
  1250. package/lib/module/metro/index.js.map +1 -1
  1251. package/lib/module/metro/optionalDependencyStub.js +11 -11
  1252. package/lib/module/metro/optionalDependencyStub.js.map +1 -1
  1253. package/lib/module/metro/optionalModules.js +16 -16
  1254. package/lib/module/metro/optionalModules.js.map +1 -1
  1255. package/lib/module/pipeline/dispatcher/dispatcher.js.map +1 -1
  1256. package/lib/module/pipeline/envelope/envelope.js.map +1 -1
  1257. package/lib/module/pipeline/envelope/serializer.js.map +1 -1
  1258. package/lib/module/pipeline/processors/dedupe.js.map +1 -1
  1259. package/lib/module/pipeline/processors/enrich.js.map +1 -1
  1260. package/lib/module/pipeline/processors/sampling.js.map +1 -1
  1261. package/lib/module/pipeline/processors/sanitize.js.map +1 -1
  1262. package/lib/module/pipeline/queue/flushQueue.js +4 -4
  1263. package/lib/module/pipeline/queue/flushQueue.js.map +1 -1
  1264. package/lib/module/pipeline/queue/memoryQueue.js.map +1 -1
  1265. package/lib/module/pipeline/queue/persistentQueue.js +80 -80
  1266. package/lib/module/pipeline/queue/persistentQueue.js.map +1 -1
  1267. package/lib/module/pipeline/queue/queuePolicy.js.map +1 -1
  1268. package/lib/module/pipeline/scheduler/flushScheduler.js.map +1 -1
  1269. package/lib/module/pipeline/scheduler/retryPolicy.js +2 -2
  1270. package/lib/module/pipeline/scheduler/retryPolicy.js.map +1 -1
  1271. package/lib/module/public/ScaleBunFacade.js +274 -274
  1272. package/lib/module/public/ScaleBunFacade.js.map +1 -1
  1273. package/lib/module/public/ScaleBunProvider.js +3 -3
  1274. package/lib/module/public/ScaleBunProvider.js.map +1 -1
  1275. package/lib/module/public/typedTracker.js +36 -36
  1276. package/lib/module/public/typedTracker.js.map +1 -1
  1277. package/lib/module/public/types.js.map +1 -1
  1278. package/lib/module/push/PushManager.js +21 -21
  1279. package/lib/module/push/PushManager.js.map +1 -1
  1280. package/lib/module/push/adapters/ManualAdapter.js +14 -14
  1281. package/lib/module/push/adapters/ManualAdapter.js.map +1 -1
  1282. package/lib/module/push/adapters/NativeBridgeAdapter.js +17 -17
  1283. package/lib/module/push/adapters/NativeBridgeAdapter.js.map +1 -1
  1284. package/lib/module/push/adapters/NoopAdapter.js +5 -5
  1285. package/lib/module/push/adapters/NoopAdapter.js.map +1 -1
  1286. package/lib/module/push/adapters/RNFirebaseMessagingAdapter.js +17 -17
  1287. package/lib/module/push/adapters/RNFirebaseMessagingAdapter.js.map +1 -1
  1288. package/lib/module/push/adapters/loadMessaging.js +12 -12
  1289. package/lib/module/push/adapters/loadMessaging.js.map +1 -1
  1290. package/lib/module/push/adapters/loadNotifee.js +12 -12
  1291. package/lib/module/push/adapters/loadNotifee.js.map +1 -1
  1292. package/lib/module/push/adapters/selectAdapter.js +14 -14
  1293. package/lib/module/push/adapters/selectAdapter.js.map +1 -1
  1294. package/lib/module/push/detect/capabilities.js +19 -19
  1295. package/lib/module/push/detect/capabilities.js.map +1 -1
  1296. package/lib/module/push/index.js +3 -3
  1297. package/lib/module/push/index.js.map +1 -1
  1298. package/lib/module/push/native/nativeNotifications.js +32 -32
  1299. package/lib/module/push/native/nativeNotifications.js.map +1 -1
  1300. package/lib/module/push/types.js.map +1 -1
  1301. package/lib/module/specs/NativeReplaySdk.js +18 -18
  1302. package/lib/module/specs/NativeReplaySdk.js.map +1 -1
  1303. package/lib/module/specs/NativeScaleBunCrash.js +19 -19
  1304. package/lib/module/specs/NativeScaleBunCrash.js.map +1 -1
  1305. package/lib/module/specs/NativeScaleBunInstallReferrer.js +14 -14
  1306. package/lib/module/specs/NativeScaleBunInstallReferrer.js.map +1 -1
  1307. package/lib/module/specs/NativeScaleBunOta.js +21 -21
  1308. package/lib/module/specs/NativeScaleBunOta.js.map +1 -1
  1309. package/lib/module/specs/NativeScaleBunPerformance.js +15 -15
  1310. package/lib/module/specs/NativeScaleBunPerformance.js.map +1 -1
  1311. package/lib/module/specs/NativeScaleBunProfiler.js +16 -16
  1312. package/lib/module/specs/NativeScaleBunProfiler.js.map +1 -1
  1313. package/lib/module/specs/NativeScaleBunStorage.js +29 -29
  1314. package/lib/module/specs/NativeScaleBunStorage.js.map +1 -1
  1315. package/lib/module/storage/StorageBackend.js +83 -83
  1316. package/lib/module/storage/StorageBackend.js.map +1 -1
  1317. package/lib/module/storage/db/sqlite.js.map +1 -1
  1318. package/lib/module/storage/files/fileStore.js.map +1 -1
  1319. package/lib/module/transport/auth/sdkSession.js.map +1 -1
  1320. package/lib/module/transport/backoff/exponentialJitter.js +2 -2
  1321. package/lib/module/transport/backoff/exponentialJitter.js.map +1 -1
  1322. package/lib/module/transport/http/endpoints.js.map +1 -1
  1323. package/lib/module/transport/http/httpClient.js +3 -3
  1324. package/lib/module/transport/http/httpClient.js.map +1 -1
  1325. package/lib/module/transport/rateLimit/retryAfter.js.map +1 -1
  1326. package/lib/module/transport/signing/requestSigner.js.map +1 -1
  1327. package/lib/module/vendor/protocol/index.js +74 -74
  1328. package/lib/module/vendor/protocol/index.js.map +1 -1
  1329. package/lib/module/vendor/protocol/internal/validation.js +23 -23
  1330. package/lib/module/vendor/protocol/internal/validation.js.map +1 -1
  1331. package/lib/module/vendor/sdk-contracts/bridge.js.map +1 -1
  1332. package/lib/module/vendor/sdk-contracts/config.js.map +1 -1
  1333. package/lib/module/vendor/sdk-contracts/events.js.map +1 -1
  1334. package/lib/module/vendor/sdk-contracts/features.js.map +1 -1
  1335. package/lib/module/vendor/sdk-contracts/index.js.map +1 -1
  1336. package/lib/module/vendor/sdk-contracts/platform.js.map +1 -1
  1337. package/lib/module/vendor/sdk-contracts/session-boundary.js.map +1 -1
  1338. package/lib/module/vendor/sdk-contracts/session.js.map +1 -1
  1339. package/lib/module/vendor/vendor.manifest +10 -10
  1340. package/package.json +12 -10
  1341. package/react-native.config.js +24 -24
  1342. package/scalebun-react-native.podspec +37 -37
  1343. package/src/analytics/EventTracker.ts +462 -462
  1344. package/src/analytics/automaticEvents.ts +105 -105
  1345. package/src/analytics/batching.ts +54 -54
  1346. package/src/analytics/eventLane.ts +26 -26
  1347. package/src/bootstrap/FeatureRegistry.ts +81 -81
  1348. package/src/bootstrap/SDKBootstrapper.ts +585 -585
  1349. package/src/bucketing/fnv1a32.ts +40 -40
  1350. package/src/compat/codepush.ts +118 -118
  1351. package/src/config/ConfigManager.ts +167 -167
  1352. package/src/config/configTypes.ts +32 -32
  1353. package/src/core/architecture.ts +39 -39
  1354. package/src/core/clock/now.ts +6 -6
  1355. package/src/core/config/schema.ts +231 -231
  1356. package/src/core/constants/endpoints.ts +9 -9
  1357. package/src/core/constants/timings.ts +23 -23
  1358. package/src/core/constants/version.ts +6 -6
  1359. package/src/core/context/user.ts +26 -26
  1360. package/src/core/contracts/IFeature.ts +53 -53
  1361. package/src/core/di/container.ts +26 -26
  1362. package/src/core/encoding/base64.ts +46 -46
  1363. package/src/core/id/deviceId.ts +51 -51
  1364. package/src/core/lifecycle/appLifecycle.ts +33 -33
  1365. package/src/core/lifecycle/crashSafe.ts +29 -29
  1366. package/src/core/logger/errorClassification.ts +108 -108
  1367. package/src/core/logger/internalLogger.ts +65 -65
  1368. package/src/crypto/hmacSha256.ts +106 -106
  1369. package/src/debug/bootstrap.ts +366 -366
  1370. package/src/debug/commands.ts +597 -597
  1371. package/src/debug/configBuilder.ts +56 -56
  1372. package/src/debug/exportBridge.ts +153 -153
  1373. package/src/debug/hostResolver.ts +34 -34
  1374. package/src/debug/index.ts +25 -25
  1375. package/src/debug/metrics.ts +29 -29
  1376. package/src/debug/perf.ts +212 -212
  1377. package/src/debug/perfWiring.ts +119 -119
  1378. package/src/debug/protocol.ts +58 -58
  1379. package/src/debug/redaction.ts +290 -290
  1380. package/src/debug/replayWiring.ts +147 -147
  1381. package/src/debug/screenTracking.ts +55 -55
  1382. package/src/debug/sessionWiring.ts +59 -59
  1383. package/src/debug/stream.ts +561 -561
  1384. package/src/debug/transport.ts +439 -439
  1385. package/src/features/crash/CrashFeature.ts +52 -52
  1386. package/src/features/crash/CrashReporter.ts +140 -140
  1387. package/src/features/crash/NativeCrashFeature.ts +42 -42
  1388. package/src/features/crash/capture.ts +21 -21
  1389. package/src/features/crash/globalHandler.ts +39 -39
  1390. package/src/features/crash/index.ts +8 -8
  1391. package/src/features/crash/nativeCrashBridge.ts +132 -132
  1392. package/src/features/engage/EngageAnchor.tsx +159 -159
  1393. package/src/features/engage/EngageArchetypeRenderers.tsx +3716 -3716
  1394. package/src/features/engage/EngageInAppView.tsx +2678 -2678
  1395. package/src/features/engage/EngageInlinePlacement.tsx +169 -169
  1396. package/src/features/engage/EngagePromptProvider.tsx +1270 -1270
  1397. package/src/features/engage/EngagePromptView.tsx +1364 -1364
  1398. package/src/features/engage/EngageTransport.ts +668 -668
  1399. package/src/features/engage/EngageVariantContent.tsx +1483 -1483
  1400. package/src/features/engage/__test-support__/reactNativeStub.js +40 -40
  1401. package/src/features/engage/attachmentCapture.ts +45 -45
  1402. package/src/features/engage/captureVoiceAttachment.ts +81 -81
  1403. package/src/features/engage/engageCoachmarkTour.ts +120 -120
  1404. package/src/features/engage/engageGameLogic.ts +347 -347
  1405. package/src/features/engage/engageMediaSizing.ts +76 -76
  1406. package/src/features/engage/engageMultiStepSheet.ts +53 -53
  1407. package/src/features/engage/engageOutcome.ts +157 -157
  1408. package/src/features/engage/engagePushTokenBridge.ts +84 -84
  1409. package/src/features/engage/engageShakeBridge.ts +67 -67
  1410. package/src/features/engage/engageSignals.ts +40 -40
  1411. package/src/features/engage/engageStoreReviewBridge.ts +48 -48
  1412. package/src/features/engage/engageTestSeenStore.ts +95 -95
  1413. package/src/features/engage/engageThrottle.ts +440 -440
  1414. package/src/features/engage/engageTriggerEngine.ts +335 -335
  1415. package/src/features/engage/engageTypes.ts +691 -691
  1416. package/src/features/engage/engageVariantResolver.ts +364 -364
  1417. package/src/features/engage/engageWindowInsets.ts +108 -108
  1418. package/src/features/engage/gestureTriggerDetector.ts +83 -83
  1419. package/src/features/engage/transcription/TranscriptionProvider.ts +68 -68
  1420. package/src/features/install-referrer/installReferrer.ts +112 -112
  1421. package/src/features/journey/ScaleBunDebugRoot.tsx +726 -726
  1422. package/src/features/journey/ScaleBunFlatList.tsx +39 -39
  1423. package/src/features/journey/ScaleBunImpression.tsx +109 -109
  1424. package/src/features/journey/ScaleBunScrollView.tsx +72 -72
  1425. package/src/features/journey/ScaleBunSectionList.tsx +39 -39
  1426. package/src/features/journey/calibrationContext.ts +53 -53
  1427. package/src/features/journey/gestureBuffer.ts +59 -59
  1428. package/src/features/journey/gestureDetector.ts +162 -162
  1429. package/src/features/journey/impression.ts +92 -92
  1430. package/src/features/journey/journeyManager.ts +466 -466
  1431. package/src/features/journey/journeyTypes.ts +215 -215
  1432. package/src/features/journey/navDetector.ts +149 -149
  1433. package/src/features/journey/screenshotHelper.ts +137 -137
  1434. package/src/features/journey/targetRegistry.ts +43 -43
  1435. package/src/features/journey/touchTarget.ts +128 -128
  1436. package/src/features/navigation/AutoScreenDetector.ts +448 -448
  1437. package/src/features/network/NetworkFeature.ts +144 -144
  1438. package/src/features/network/index.ts +31 -31
  1439. package/src/features/ota/OtaEventEmitter.ts +128 -128
  1440. package/src/features/ota/OtaOrchestrator.ts +323 -323
  1441. package/src/features/ota/OtaTypes.ts +62 -62
  1442. package/src/features/ota/useOtaUpdate.ts +134 -134
  1443. package/src/features/performance/PerformanceFeature.ts +584 -584
  1444. package/src/features/performance/collectors/AppLaunchCollector.ts +117 -117
  1445. package/src/features/performance/collectors/AutoScreenLoadCollector.ts +258 -258
  1446. package/src/features/performance/collectors/CustomTraceCollector.ts +116 -116
  1447. package/src/features/performance/collectors/FrameMetricsCollector.ts +119 -119
  1448. package/src/features/performance/collectors/JsStallCollector.ts +165 -165
  1449. package/src/features/performance/collectors/NetworkPerfCollector.ts +69 -69
  1450. package/src/features/performance/collectors/ScreenLoadCollector.ts +95 -95
  1451. package/src/features/performance/collectors/UiHangCollector.ts +98 -98
  1452. package/src/features/performance/config.ts +136 -136
  1453. package/src/features/performance/getNativePerformanceModule.ts +38 -38
  1454. package/src/features/performance/index.ts +28 -28
  1455. package/src/features/performance/metrics/MetricsEngine.ts +152 -152
  1456. package/src/features/performance/models.ts +235 -235
  1457. package/src/features/performance/transport/PerformanceTransport.ts +143 -143
  1458. package/src/features/profiler/ProfilerFeature.ts +661 -661
  1459. package/src/features/profiler/config.ts +230 -230
  1460. package/src/features/profiler/contracts.ts +176 -176
  1461. package/src/features/profiler/index.ts +45 -45
  1462. package/src/features/profiler/models.ts +430 -430
  1463. package/src/features/profiler/transport/ProfilerTransport.ts +93 -93
  1464. package/src/features/replay/bridge/adapters/bridgeAdapter.ts +230 -230
  1465. package/src/features/replay/bridge/eventEmitter.ts +176 -176
  1466. package/src/features/replay/bridge/nativeModule.ts +241 -241
  1467. package/src/features/replay/core/clock/clock.ts +38 -38
  1468. package/src/features/replay/core/config/defaults.ts +66 -66
  1469. package/src/features/replay/core/config/validator.ts +113 -113
  1470. package/src/features/replay/core/env/environmentDetector.ts +21 -21
  1471. package/src/features/replay/core/errors/safeCall.ts +34 -34
  1472. package/src/features/replay/core/ids/sessionId.ts +44 -44
  1473. package/src/features/replay/core/logger/logger.ts +40 -40
  1474. package/src/features/replay/core/privacy/privacyTypes.ts +41 -41
  1475. package/src/features/replay/core/queue/boundedQueue.ts +71 -71
  1476. package/src/features/replay/integrations/alert/alertInstrumentation.ts +277 -277
  1477. package/src/features/replay/integrations/logs/consoleIntegration.ts +116 -116
  1478. package/src/features/replay/integrations/network/networkAdapter.ts +128 -128
  1479. package/src/features/replay/integrations/react-navigation/navigationIntegration.ts +89 -89
  1480. package/src/features/replay/integrations/touch/ReplayRoot.tsx +114 -114
  1481. package/src/features/replay/pipeline/batching/batchManager.ts +133 -133
  1482. package/src/features/replay/pipeline/envelope/envelopeBuilder.ts +66 -66
  1483. package/src/features/replay/pipeline/retry/retryPolicy.ts +62 -62
  1484. package/src/features/replay/pipeline/transport/transportTypes.ts +85 -85
  1485. package/src/features/replay/public/api.ts +364 -364
  1486. package/src/features/replay/public/enums.ts +78 -78
  1487. package/src/features/replay/public/types.ts +297 -297
  1488. package/src/features/replay/replay/breadcrumbs/breadcrumbCollector.ts +115 -115
  1489. package/src/features/replay/replay/frames/frameModels.ts +45 -45
  1490. package/src/features/replay/replay/session/sessionOrchestrator.ts +286 -286
  1491. package/src/features/replay/replay/timeline/timelineModels.ts +129 -129
  1492. package/src/features/replay/transport/BackendReplayTransport.ts +215 -215
  1493. package/src/features/replay/transport/CompositeReplayTransport.ts +82 -82
  1494. package/src/features/replay/transport/DesktopReplayTransport.ts +140 -140
  1495. package/src/features/replay/transport/ReplayTransport.ts +84 -84
  1496. package/src/features/session/BackendSessionAdapter.ts +1233 -1233
  1497. package/src/features/session/DesktopSessionTransport.ts +128 -128
  1498. package/src/features/session/JourneyEventPipeline.ts +273 -273
  1499. package/src/features/session/ReplayCaptureManager.ts +946 -946
  1500. package/src/features/session/ScrollTracker.ts +166 -166
  1501. package/src/features/session/SessionManager.ts +1209 -1209
  1502. package/src/features/session/SyncDecisionEngine.ts +117 -117
  1503. package/src/features/session/index.ts +88 -88
  1504. package/src/features/session/nativeCapture.ts +38 -38
  1505. package/src/features/session/outboxFrameCapture.ts +74 -74
  1506. package/src/features/session/sessionTypes.ts +491 -491
  1507. package/src/features/skan/skanBridge.ts +61 -61
  1508. package/src/features/skan/skanConversionManager.ts +173 -173
  1509. package/src/index.ts +191 -191
  1510. package/src/integrations/fetch/fetchInterceptor.ts +182 -182
  1511. package/src/integrations/network/bodyCapture.ts +328 -328
  1512. package/src/integrations/xhr/xhrInterceptor.ts +231 -231
  1513. package/src/metro/index.ts +164 -164
  1514. package/src/metro/optionalDependencyStub.ts +13 -13
  1515. package/src/metro/optionalModules.ts +27 -27
  1516. package/src/pipeline/dispatcher/dispatcher.ts +22 -22
  1517. package/src/pipeline/envelope/envelope.ts +31 -31
  1518. package/src/pipeline/envelope/serializer.ts +14 -14
  1519. package/src/pipeline/processors/enrich.ts +11 -11
  1520. package/src/pipeline/processors/sanitize.ts +23 -23
  1521. package/src/pipeline/queue/flushQueue.ts +144 -144
  1522. package/src/pipeline/queue/memoryQueue.ts +31 -31
  1523. package/src/pipeline/queue/persistentQueue.ts +414 -414
  1524. package/src/pipeline/scheduler/flushScheduler.ts +47 -47
  1525. package/src/pipeline/scheduler/retryPolicy.ts +8 -8
  1526. package/src/public/ScaleBunFacade.ts +1479 -1479
  1527. package/src/public/ScaleBunProvider.tsx +91 -91
  1528. package/src/public/typedTracker.ts +123 -123
  1529. package/src/public/types.ts +312 -312
  1530. package/src/push/PushManager.ts +318 -318
  1531. package/src/push/adapters/ManualAdapter.ts +100 -100
  1532. package/src/push/adapters/NativeBridgeAdapter.ts +142 -142
  1533. package/src/push/adapters/NoopAdapter.ts +46 -46
  1534. package/src/push/adapters/RNFirebaseMessagingAdapter.ts +271 -271
  1535. package/src/push/adapters/loadMessaging.ts +24 -24
  1536. package/src/push/adapters/loadNotifee.ts +29 -29
  1537. package/src/push/adapters/selectAdapter.ts +176 -176
  1538. package/src/push/detect/capabilities.ts +124 -124
  1539. package/src/push/index.ts +22 -22
  1540. package/src/push/native/nativeNotifications.ts +216 -216
  1541. package/src/push/types.ts +159 -159
  1542. package/src/specs/NativeReplaySdk.ts +99 -99
  1543. package/src/specs/NativeScaleBunCrash.ts +36 -36
  1544. package/src/specs/NativeScaleBunInstallReferrer.ts +29 -29
  1545. package/src/specs/NativeScaleBunOta.ts +85 -85
  1546. package/src/specs/NativeScaleBunPerformance.ts +34 -34
  1547. package/src/specs/NativeScaleBunProfiler.ts +41 -41
  1548. package/src/specs/NativeScaleBunStorage.ts +59 -59
  1549. package/src/storage/StorageBackend.ts +272 -272
  1550. package/src/transport/auth/sdkSession.ts +27 -27
  1551. package/src/transport/backoff/exponentialJitter.ts +9 -9
  1552. package/src/transport/http/endpoints.ts +33 -33
  1553. package/src/transport/http/httpClient.ts +73 -73
  1554. package/src/vendor/protocol/index.ts +391 -391
  1555. package/src/vendor/protocol/internal/validation.ts +497 -497
  1556. package/src/vendor/sdk-contracts/bridge.ts +162 -162
  1557. package/src/vendor/sdk-contracts/config.ts +192 -192
  1558. package/src/vendor/sdk-contracts/events.ts +50 -50
  1559. package/src/vendor/sdk-contracts/features.ts +42 -42
  1560. package/src/vendor/sdk-contracts/index.ts +98 -98
  1561. package/src/vendor/sdk-contracts/platform.ts +42 -42
  1562. package/src/vendor/sdk-contracts/session-boundary.ts +55 -55
  1563. package/src/vendor/sdk-contracts/session.ts +225 -225
  1564. package/src/vendor/vendor.manifest +10 -10
@@ -1,1270 +1,1270 @@
1
- /**
2
- * ScaleBun SDK — Engage Prompt Provider (campaign renderer core, D4)
3
- *
4
- * Wraps the host app and owns the campaign-render lifecycle for the shared
5
- * cross-platform JS overlay:
6
- * 1. on a trigger (app-controlled via `showEngagePrompt()` and/or the campaign's
7
- * own `trigger` from config), calls `facade.engage.fetchConfig()`,
8
- * 2. runs the throttle/decision core (`selectCampaignToRender`) to pick which
9
- * campaign — if any — is eligible, honoring frequency caps,
10
- * 3. mounts the parameterized `EngagePromptView` (Open/Closed: NPS now,
11
- * ratings/feedback/survey later via the renderer registry),
12
- * 4. on submit → `facade.engage.submitResponse({ surveyId, score, text })`
13
- * (transport stamps `responseId` UUID + `schemaVersion` per contract),
14
- * records the impression as completed, and emits an in-app dismiss/submit
15
- * tracking event,
16
- * 5. on dismiss → `facade.engage.trackEvent` with a `dismiss` event.
17
- *
18
- * The provider depends only on the `engage` namespace shape — NOT the whole
19
- * facade — so it stays decoupled and testable, and reuses the existing transport
20
- * (no second HTTP path).
21
- *
22
- * IN-APP MESSAGES (the second Engage family, §2.4/§2.5) are surfaced by this SAME
23
- * provider — NOT a parallel one. `showInAppMessage()` fetches the config, picks an
24
- * eligible message from `inAppMessages[]` (shared throttle store), and mounts the
25
- * config-driven `EngageInAppView` (banner/modal/overlay). Events: `impression` on
26
- * show, `click` on CTA tap (the resolved deep link is surfaced to the host via
27
- * `onInAppDeepLink` — the SDK never opens URLs), `dismiss` on close.
28
- *
29
- * PRECEDENCE (campaign vs in-app): a campaign prompt wins the screen. If a
30
- * campaign prompt is already visible, `showInAppMessage()` is a no-op (returns
31
- * false) and the mounted in-app view is hidden while a campaign is up, so the two
32
- * families never fight for the screen.
33
- */
34
-
35
- import React, {
36
- createContext,
37
- useContext,
38
- useCallback,
39
- useEffect,
40
- useMemo,
41
- useRef,
42
- useState,
43
- type ReactNode,
44
- type ReactElement,
45
- } from 'react';
46
- import { Linking, Platform } from 'react-native';
47
- import { logger } from '../../core/logger/internalLogger';
48
- import { installEngageTriggerEngine } from './engageTriggerEngine';
49
- import { appLifecycle } from '../../core/lifecycle/appLifecycle';
50
- import { getDeviceId } from '../../core/id/deviceId';
51
- import { ReplaySdk } from '../replay/public/api';
52
- import { SessionManager } from '../session/SessionManager';
53
- import {
54
- EngagePromptView,
55
- type EngagePromptResult,
56
- type EngageSubmitStatus,
57
- type RatingPromptConfig,
58
- } from './EngagePromptView';
59
- import { EngageInAppView, type InAppMechanicInteraction } from './EngageInAppView';
60
- import { EngageAnchorProvider } from './EngageAnchor';
61
- import {
62
- EngageInlinePlacementProvider,
63
- createEngageInlinePlacementRegistry,
64
- resolveEngageInlinePlacement,
65
- type EngageInlineDelivery,
66
- } from './EngageInlinePlacement';
67
- import { resolveInAppPresentation } from './engageVariantResolver';
68
- import { shouldTrackInAppCta } from './engageOutcome';
69
- import type { SubmitStage } from './EngageTransport';
70
- import {
71
- EngageThrottleStore,
72
- selectCampaignToRender,
73
- selectInAppToRender,
74
- selectInAppVariant,
75
- selectLatestUnseenTest,
76
- testRunIdOf,
77
- } from './engageThrottle';
78
- import { EngageTestSeenStore } from './engageTestSeenStore';
79
- import type {
80
- EngageAttachmentDraft,
81
- EngageCampaignConfig,
82
- EngageCampaignType,
83
- EngageConfigContext,
84
- EngageConfigResponse,
85
- EngageEventInput,
86
- InAppGameRequestHandler,
87
- EngageResponseInput,
88
- InAppMessageConfig,
89
- InAppRenderSpec,
90
- InAppVariantId,
91
- RatingFunnelEventDims,
92
- RatingFunnelEventInput,
93
- RatingFunnelEventType,
94
- SurveyAnswer,
95
- SurveyImpressionInput,
96
- } from './engageTypes';
97
-
98
- /** Client-generated UUID for app-rating idempotency (D8: `clientRatingId`). */
99
- function ratingUuid(): string {
100
- return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {
101
- const r = (Math.random() * 16) | 0;
102
- const v = c === 'x' ? r : (r & 0x3) | 0x8;
103
- return v.toString(16);
104
- });
105
- }
106
-
107
- /** Preserve a multi-question survey answer in the keyed wire shape (§1.4). */
108
- export function toWireAnswers(
109
- answers: SurveyAnswer[],
110
- ): { key: string; value: string | number | string[] }[] {
111
- return answers.map((a) => ({
112
- key: a.key,
113
- value: a.value,
114
- }));
115
- }
116
-
117
- /**
118
- * Resolve the canonical session id for response linkage (contract §1/§7).
119
- * Primary source is `SessionManager.currentSessionId` — the always-on analytics
120
- * session id (`rs-…`) that the replay recording attaches to (and that `/sessions/:id`
121
- * keys on). `ReplaySdk.sessionId` (the orchestrator's recording id) is only set
122
- * while a recording is mid-flight and reads `null` at submit time, so it is a
123
- * fallback, not the primary. Returns `undefined` (not `null`) so the optional wire
124
- * field is simply omitted when no session is active.
125
- */
126
- function currentSessionId(): string | undefined {
127
- return (
128
- SessionManager.getExistingInstance()?.currentSessionId ??
129
- ReplaySdk.sessionId ??
130
- undefined
131
- );
132
- }
133
-
134
- /**
135
- * The host app version for by-version analytics (contract §1). Read from the
136
- * SAME synchronous source the SDK's rating lane already uses
137
- * (`SessionManager.currentSessionMetadata.appVersion`, populated from native
138
- * device info) — NOT hardcoded, and NOT the SDK build version. `undefined` when
139
- * no session metadata is available yet, so the optional field is omitted.
140
- */
141
- function currentAppVersion(): string | undefined {
142
- return SessionManager.getExistingInstance()?.currentSessionMetadata?.appVersion ?? undefined;
143
- }
144
-
145
- /**
146
- * Device platform as the `'android' | 'ios'` wire union (contract §1). Shared JS
147
- * path — NOT platform-gated — so Android and iOS both stamp their own value.
148
- * `Platform.OS` also yields `'windows' | 'macos' | 'web'`; those are out of the
149
- * SDK's mobile scope and intentionally collapse to `undefined` (field omitted).
150
- */
151
- function currentPlatform(): 'android' | 'ios' | undefined {
152
- return Platform.OS === 'android' || Platform.OS === 'ios' ? Platform.OS : undefined;
153
- }
154
-
155
- /**
156
- * Build the config-serve context (contract §1.3 query). ALWAYS carries `deviceId`
157
- * — the backend keys per-device test previews on it, so omitting it would hide a
158
- * "Send Test" preview from the very device it was queued for (T1). `platform`/
159
- * `appVersion` ride along for server-side targeting; both honest, both omitted when
160
- * unresolved. A caller-supplied `context` (manual show) overrides field-by-field.
161
- */
162
- function buildConfigContext(
163
- engage: EngageRendererFacade,
164
- override?: EngageConfigContext,
165
- ): EngageConfigContext {
166
- const identifiedUserId = engage.getIdentifiedUserId?.();
167
- return {
168
- deviceId: getDeviceId(),
169
- ...(currentPlatform() ? { platform: currentPlatform() } : {}),
170
- ...(currentAppVersion() ? { appVersion: currentAppVersion() } : {}),
171
- ...(identifiedUserId ? { endUserId: identifiedUserId } : {}),
172
- ...override,
173
- };
174
- }
175
-
176
- /**
177
- * Build the rating-funnel breakdown dimensions (ratings-rebuild CONTRACT §1.2 `dims`)
178
- * from the SAME live session metadata the response builder reads — NOT hardcoded.
179
- * Only honest, present values are included; `country`/`locale`/`acquisitionSource`
180
- * are intentionally omitted here (no on-device source yet) so the backend reports
181
- * them as absent rather than fabricated.
182
- */
183
- function currentRatingDims(): RatingFunnelEventDims {
184
- const meta = SessionManager.getExistingInstance()?.currentSessionMetadata;
185
- const platform = currentPlatform();
186
- return {
187
- ...(platform ? { platform } : {}),
188
- ...(meta?.appVersion ? { appVersion: meta.appVersion } : {}),
189
- ...(meta?.osVersion ? { osVersion: meta.osVersion } : {}),
190
- ...(meta?.deviceModel ? { deviceModel: meta.deviceModel } : {}),
191
- };
192
- }
193
-
194
- /**
195
- * The slice of the SDK facade the renderer consumes (the `engage` namespace).
196
- * Matching this shape — rather than importing the facade — keeps the renderer a
197
- * pure consumer of the foundation transport and trivially testable.
198
- */
199
- export interface EngageRendererFacade {
200
- /** External user id last supplied through ScaleBun.identify(). */
201
- getIdentifiedUserId?: () => string | undefined;
202
- fetchConfig: (context?: EngageConfigContext) => Promise<EngageConfigResponse | null>;
203
- trackCoachmarkEvent?: (name: string, properties: Record<string, unknown>) => void;
204
- submitResponse: (input: EngageResponseInput) => void;
205
- /**
206
- * [P3-e] Submit a response with native attachments (screenshot/voice). Optional
207
- * so a host wired to an older facade still renders prompts (media silently
208
- * degrades to a plain response).
209
- */
210
- submitResponseWithAttachments?: (
211
- input: EngageResponseInput,
212
- attachments: EngageAttachmentDraft[],
213
- ) => void;
214
- /**
215
- * [Slice D5] CONFIRMED submit used by the reusable submitting→success→error state
216
- * machine: resolves only on real server persistence, rejects on failure, idempotent
217
- * on `responseId`. Optional so an older facade still renders prompts (falls back to
218
- * the fire-and-forget lanes, which resolve immediately).
219
- */
220
- submitResponseConfirmed?: (
221
- input: EngageResponseInput,
222
- attachments: EngageAttachmentDraft[],
223
- opts: { responseId: string; onStage?: (stage: SubmitStage) => void },
224
- ) => Promise<void>;
225
- trackEvent: (input: EngageEventInput) => void;
226
- trackSurveyImpression?: (input: SurveyImpressionInput) => void;
227
- /**
228
- * Force-flush queued in-app events immediately (bypassing the batch threshold/timer).
229
- * Called right after a TEST preview's impression/dismiss ACK so the backend consumes
230
- * the one-shot preview row before the app can be backgrounded/killed — otherwise a
231
- * still-`delivered` row re-serves on the next reopen. Optional: an older facade simply
232
- * relies on the periodic flush (eventual consistency).
233
- */
234
- flushEvents?: () => void;
235
- /**
236
- * Submit a 1–5 app-store rating via the EXISTING rating lane (NOT
237
- * submitResponse — D1 keeps app-ratings a distinct funnel). The provider
238
- * passes a client `clientRatingId` for idempotency (D8). Optional so a host
239
- * that never shows RATING_PROMPT need not supply it.
240
- */
241
- submitRating?: (input: {
242
- rating: number;
243
- comment?: string;
244
- source?: 'in_app' | 'prompt' | 'manual';
245
- clientRatingId?: string;
246
- }) => unknown;
247
- /**
248
- * Emit a rating-funnel tracking fact (ratings-rebuild CONTRACT §1.2) — eligible/
249
- * shown/dismissed/selected/redirect. NOT a campaign response (D1). Optional so an
250
- * older facade still renders rating prompts (the funnel just goes uninstrumented).
251
- */
252
- emitRatingEvent?: (input: RatingFunnelEventInput) => void;
253
- /**
254
- * Trigger the native in-app review sheet (D5). Resolves `true` only when the OS
255
- * flow ran/resolved after a positive route, so the provider emits
256
- * `store_redirect_clicked` solely on a `true` result. Optional/fail-soft.
257
- */
258
- requestStoreReview?: () => Promise<boolean>;
259
- }
260
-
261
- /**
262
- * Host-app RATING_PROMPT routing config. The store deeplink is NEVER hardcoded —
263
- * the host supplies either a static `storeUrl` or an `onHighRating` callback (e.g.
264
- * `Linking.openURL(...)` / native `requestReview()`), and an `onLowRating` for the
265
- * feedback hand-off. The provider only decides WHICH callback to invoke.
266
- */
267
- export interface EngageRatingRouting extends RatingPromptConfig {
268
- /** App-store deeplink opened on a high rating (host owns the navigation). */
269
- storeUrl?: string;
270
- /** Called on a high rating (>= threshold). Receives the resolved store URL if set. */
271
- onHighRating?: (info: { rating: number; campaign: EngageCampaignConfig; storeUrl?: string }) => void;
272
- /** Called on a low rating when routing to feedback (host opens its form). */
273
- onLowRating?: (info: { rating: number; campaign: EngageCampaignConfig }) => void;
274
- }
275
-
276
- export interface ShowEngagePromptOptions {
277
- /** Restrict to specific campaign types. Defaults to `['NPS']` (NPS-first slice). */
278
- types?: EngageCampaignType[];
279
- /** Match a campaign's `targetScreen` to the current screen. */
280
- screen?: string;
281
- /**
282
- * Restrict to campaigns whose `trigger` equals this value (behavioral-trigger
283
- * path, e.g. `'screen_exit'`). Omitted ⇒ trigger-agnostic (manual fire).
284
- */
285
- trigger?: string;
286
- /** Event name for `custom_event` / `after_purchase` (matches `triggerConfig.event`). */
287
- event?: string;
288
- /** Action label for `failed_action` (matches `triggerConfig.action`). */
289
- action?: string;
290
- /** Fired `time_in_app` threshold, used to select only that configured timer. */
291
- seconds?: number;
292
- /** App/user context forwarded to the config fetch for server-side targeting. */
293
- context?: EngageConfigContext;
294
- }
295
-
296
- export interface ShowInAppMessageOptions {
297
- /** Match a message's `targetScreen` to the current screen. */
298
- screen?: string;
299
- /**
300
- * Restrict to messages whose `trigger` equals this value (behavioral-trigger
301
- * path, e.g. `'session_start'`). Omitted ⇒ trigger-agnostic (manual host call).
302
- */
303
- trigger?: string;
304
- /** Fired business/custom event name, matched against `message.eventName`. */
305
- event?: string;
306
- /** Fired action value for forward-compatible action-specific messages. */
307
- action?: string;
308
- /** Fired `time_delay` threshold, used to select only that configured message. */
309
- seconds?: number;
310
- /** App/user context forwarded to the config fetch for server-side targeting. */
311
- context?: EngageConfigContext;
312
- }
313
-
314
- /**
315
- * The host's deep-link sink for an in-app CTA tap. The SDK NEVER opens a URL — it
316
- * hands the resolved `deepLink` (and full message/cta) to the host, which decides
317
- * how to navigate (e.g. `Linking.openURL` / a router push). Only fired for a CTA
318
- * whose `action` resolves to a link with a `deepLink`.
319
- */
320
- export type InAppDeepLinkHandler = (info: {
321
- message: InAppMessageConfig;
322
- cta: NonNullable<InAppRenderSpec['cta']>;
323
- deepLink: string;
324
- }) => void;
325
-
326
- /** Imperative controller a host app uses to trigger a prompt / in-app message. */
327
- export interface EngagePromptController {
328
- /** Fetch config, pick an eligible campaign, and show it. Returns whether one was shown. */
329
- showEngagePrompt: (options?: ShowEngagePromptOptions) => Promise<boolean>;
330
- /** Dismiss the currently visible prompt (no response submitted). */
331
- dismissEngagePrompt: () => void;
332
- /**
333
- * Fetch config, pick an eligible in-app message (`inAppMessages[]`), and show
334
- * it. Returns whether one was shown. PRECEDENCE: a campaign prompt already on
335
- * screen wins — an in-app message is NOT shown over it (see provider doc).
336
- */
337
- showInAppMessage: (options?: ShowInAppMessageOptions) => Promise<boolean>;
338
- /** Dismiss the currently visible in-app message (emits a `dismiss` event). */
339
- dismissInAppMessage: () => void;
340
- }
341
-
342
- const EngagePromptContext = createContext<EngagePromptController | null>(null);
343
-
344
- export interface EngagePromptProviderProps {
345
- /** The SDK facade's `engage` namespace (e.g. `ScaleBun.engage`). */
346
- engage: EngageRendererFacade;
347
- /** Default campaign types to consider. Defaults to NPS-first. */
348
- defaultTypes?: EngageCampaignType[];
349
- /**
350
- * RATING_PROMPT routing config (host-supplied). The app-store deeplink and
351
- * feedback hand-off are NEVER hardcoded in the SDK — supplied here.
352
- */
353
- ratingRouting?: EngageRatingRouting;
354
- /**
355
- * Host sink for an in-app message CTA deep link. The SDK never opens URLs —
356
- * it surfaces the resolved `deepLink` here for the host to navigate. Optional:
357
- * a host that never uses link-action CTAs need not supply it.
358
- */
359
- onInAppDeepLink?: InAppDeepLinkHandler;
360
- /**
361
- * Required when a production gamified campaign is used. The SDK calls this
362
- * only at play/load/check-in/quiz resolution time; the host's authenticated
363
- * backend owns eligibility, granting, and the returned result.
364
- */
365
- onInAppGameRequest?: InAppGameRequestHandler;
366
- /**
367
- * DEV/TEST ONLY — poll interval (ms) for queued test previews while the app is
368
- * already foregrounded. `checkForPreview` runs on mount + every AppState→active,
369
- * which covers "reopen the app". But if you press "Send Test" while the app is
370
- * ALREADY open and in the foreground, there is no background→foreground edge to
371
- * trigger a refetch. Setting e.g. `previewPollMs={4000}` makes a warm, foreground
372
- * app pick up a Send Test within a few seconds with no app switch. Leave UNSET in
373
- * production (0/undefined ⇒ no polling — the foreground/cold-start fetch is enough).
374
- */
375
- previewPollMs?: number;
376
- children: ReactNode;
377
- }
378
-
379
- const DEFAULT_TYPES: EngageCampaignType[] = ['NPS'];
380
-
381
- /**
382
- * Provider that mounts the shared overlay and exposes the imperative controller
383
- * via `useEngagePrompt()`.
384
- */
385
- export function EngagePromptProvider({
386
- engage,
387
- defaultTypes,
388
- ratingRouting,
389
- onInAppDeepLink,
390
- onInAppGameRequest,
391
- previewPollMs,
392
- children,
393
- }: EngagePromptProviderProps): ReactElement {
394
- const [active, setActive] = useState<EngageCampaignConfig | null>(null);
395
- const [activeInApp, setActiveInApp] = useState<InAppMessageConfig | null>(null);
396
- const [inlineFallbackMessageId, setInlineFallbackMessageId] = useState<string | null>(null);
397
- const [inlinePlacementRevision, setInlinePlacementRevision] = useState(0);
398
- const inlinePlacementRegistry = useMemo(createEngageInlinePlacementRegistry, []);
399
- const shownInAppMessageIdRef = useRef<string | null>(null);
400
- // Resolved A/B arm for the active in-app message (D8/J6). Held in a ref: it is
401
- // render-stable metadata (the chosen `spec` drives the view, the `variant` id
402
- // rides the lifecycle events) and must not perturb the precedence that keys off
403
- // `activeInApp`. `null` when no message is active (or it has no experiment).
404
- const activeInAppVariantRef = useRef<
405
- { variant: InAppVariantId; spec: InAppRenderSpec } | null
406
- >(null);
407
- // Show-time screen of the currently-active campaign prompt (contract §1
408
- // `screen`). Held in a ref alongside `active` — it is render-irrelevant
409
- // metadata read only at submit, so it needs no re-render and must not perturb
410
- // the campaign-vs-in-app precedence which keys off `active`/`activeInApp`.
411
- const activeScreenRef = useRef<string | undefined>(undefined);
412
- const surveyStartedRef = useRef<string | null>(null);
413
- // [T1] Test previews bypass the throttle store and the backend re-serves them on
414
- // EVERY config poll until TTL — great for "reopen the app and see it again", but it
415
- // means a dismissed preview would re-appear on the next warm poll. This session set
416
- // records previews the user already closed (dismiss/CTA) so we don't re-show the SAME
417
- // one. It is in-memory only: a cold restart clears it, so reopening the app still
418
- // shows the queued test (the intended QA behavior).
419
- const consumedPreviewIds = useRef<Set<string>>(new Set());
420
- // [T1] Persistent dedupe for ONE-SHOT test delivery — survives cold restarts (unlike
421
- // consumedPreviewIds above). A testRunId is recorded here AFTER it actually renders, so
422
- // reopening the app does NOT re-show a test the device already displayed. This is the
423
- // fix for "close/open and the old test re-appears, and they stack up". Separate from the
424
- // throttle store so production frequency caps never block a fresh test and vice-versa.
425
- const seenTestsRef = useRef<EngageTestSeenStore | null>(null);
426
- if (seenTestsRef.current === null) {
427
- seenTestsRef.current = new EngageTestSeenStore();
428
- }
429
- // One persistent throttle store for the provider lifetime — SHARED by campaigns
430
- // and in-app messages so both honor the same per-id frequency caps.
431
- const storeRef = useRef<EngageThrottleStore | null>(null);
432
- if (storeRef.current === null) {
433
- storeRef.current = new EngageThrottleStore();
434
- }
435
- const types = defaultTypes ?? DEFAULT_TYPES;
436
-
437
- // ─── Reusable submit state machine (Slice D5) ────────────────────────────
438
- // ONE machine for EVERY question type. `responseIdRef` is the idempotency key,
439
- // generated once per prompt and REUSED on retry so a re-send can't duplicate.
440
- // `submitCtxRef` holds the campaign+result so retry re-runs the same submit.
441
- const [submitStatus, setSubmitStatus] = useState<EngageSubmitStatus>({ phase: 'idle' });
442
- const responseIdRef = useRef<string | null>(null);
443
- const submitCtxRef = useRef<{ campaign: EngageCampaignConfig; result: EngagePromptResult } | null>(null);
444
- const successTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);
445
-
446
- const resetSubmit = useCallback((): void => {
447
- if (successTimerRef.current) {
448
- clearTimeout(successTimerRef.current);
449
- successTimerRef.current = null;
450
- }
451
- responseIdRef.current = null;
452
- submitCtxRef.current = null;
453
- setSubmitStatus({ phase: 'idle' });
454
- }, []);
455
-
456
- // Single campaign tracking lane (mirrors trackInApp). `impression` on show,
457
- // `completion` on submit, `dismiss` on close — the §2.5 analytics events that
458
- // back the response-rate / completion KPIs (P3-e #2). Distinct from the local
459
- // throttle store, which only counts impressions for frequency caps.
460
- const trackCampaign = useCallback(
461
- (campaign: EngageCampaignConfig, eventType: 'impression' | 'completion' | 'dismiss') => {
462
- try {
463
- engage.trackEvent({
464
- campaignId: campaign.id,
465
- channel: 'inapp',
466
- type: eventType,
467
- deviceId: getDeviceId(),
468
- });
469
- } catch (err) {
470
- logger.debug('[Engage] trackEvent failed:', (err as Error)?.message);
471
- }
472
- },
473
- [engage],
474
- );
475
-
476
- const trackSurveyStage = useCallback(
477
- (campaign: EngageCampaignConfig, stage: 'shown' | 'started'): void => {
478
- if (campaign.type === 'RATING_PROMPT' || campaign.type === 'RATINGS_PROMPT') return;
479
- try {
480
- engage.trackSurveyImpression?.({
481
- surveyId: campaign.id,
482
- stage,
483
- sessionId: currentSessionId(),
484
- deviceId: getDeviceId(),
485
- platform: currentPlatform(),
486
- appVersion: currentAppVersion(),
487
- screen: activeScreenRef.current,
488
- });
489
- } catch (err) {
490
- logger.debug('[Engage] survey impression failed:', (err as Error)?.message);
491
- }
492
- },
493
- [engage],
494
- );
495
-
496
- const isRatingType = (type: EngageCampaignType): boolean =>
497
- type === 'RATING_PROMPT' || type === 'RATINGS_PROMPT';
498
-
499
- // Rating-funnel emit lane (ratings-rebuild CONTRACT §1.2). Distinct from
500
- // trackCampaign (the §2.5 in-app analytics lane) and from submitRating (the D1
501
- // app-rating lane): these are dimensioned FACTS feeding the Overview funnel and
502
- // are NEVER counted as responses. `stars` rides only on `rating_selected`.
503
- const emitRatingFunnel = useCallback(
504
- (
505
- campaign: EngageCampaignConfig,
506
- type: RatingFunnelEventType,
507
- extra?: { stars?: number },
508
- ): void => {
509
- try {
510
- engage.emitRatingEvent?.({
511
- type,
512
- sessionId: currentSessionId(),
513
- userId: engage.getIdentifiedUserId?.(),
514
- promptId: campaign.id,
515
- triggerId: campaign.trigger,
516
- ...(extra?.stars !== undefined ? { stars: extra.stars } : {}),
517
- dims: currentRatingDims(),
518
- });
519
- } catch (err) {
520
- logger.debug('[Engage] emitRatingEvent failed:', (err as Error)?.message);
521
- }
522
- },
523
- [engage],
524
- );
525
-
526
- const dismissEngagePrompt = useCallback((): void => {
527
- setActive((current) => {
528
- if (current) {
529
- trackCampaign(current, 'dismiss');
530
- // Rating funnel: a close without a selection is a funnel drop.
531
- if (isRatingType(current.type)) emitRatingFunnel(current, 'rating_prompt_dismissed');
532
- }
533
- return null;
534
- });
535
- activeScreenRef.current = undefined;
536
- surveyStartedRef.current = null;
537
- resetSubmit();
538
- }, [trackCampaign, resetSubmit, emitRatingFunnel]);
539
-
540
- // The actual submit run — used by both the first submit and a retry. Reads
541
- // `submitCtxRef` + `responseIdRef` so a retry re-sends with the SAME idempotency
542
- // key. Resolves to `success` ONLY on confirmed persistence; `error` on failure.
543
- const runSubmit = useCallback(async (): Promise<void> => {
544
- const ctx = submitCtxRef.current;
545
- if (!ctx) return;
546
- const { campaign, result } = ctx;
547
- const store = storeRef.current;
548
- const responseId = responseIdRef.current ?? (responseIdRef.current = ratingUuid());
549
-
550
- setSubmitStatus({ phase: 'submitting', stage: 'saving' });
551
- try {
552
- if (isRatingType(campaign.type)) {
553
- // RATING_PROMPT submits via the EXISTING app-rating lane (D1), NOT
554
- // submitResponse, with a client clientRatingId for idempotency. Awaited
555
- // so the loading state reflects the real round-trip.
556
- const rating = typeof result.score === 'number' ? result.score : 0;
557
- await Promise.resolve(
558
- engage.submitRating?.({ rating, source: 'prompt', clientRatingId: responseId }),
559
- );
560
- // Funnel: user picked 1–5★ (carries stars). Emitted regardless of route.
561
- emitRatingFunnel(campaign, 'rating_selected', { stars: rating });
562
- // Routing decided by the view (`route`), executed against host-supplied
563
- // callbacks/URL — the deeplink is never hardcoded.
564
- if (result.route === 'store') {
565
- // D5: prefer the genuinely-native in-app review sheet. `store_redirect_clicked`
566
- // fires ONLY when an actual store route resolves (native review ran, or a
567
- // host-supplied deeplink/callback executed) — never speculatively.
568
- let redirected = false;
569
- if (engage.requestStoreReview) {
570
- redirected = await engage.requestStoreReview();
571
- }
572
- const storeUrl = campaign.storeUrl ?? ratingRouting?.storeUrl;
573
- if (ratingRouting?.onHighRating) {
574
- ratingRouting.onHighRating({ rating, campaign, storeUrl });
575
- redirected = true;
576
- } else if (!redirected && storeUrl) {
577
- redirected = await Linking.openURL(storeUrl).then(() => true).catch(() => false);
578
- }
579
- if (redirected) emitRatingFunnel(campaign, 'store_redirect_clicked');
580
- } else if (result.route === 'feedback') {
581
- ratingRouting?.onLowRating?.({ rating, campaign });
582
- }
583
- } else {
584
- // [v2] response context (contract §1): session linkage + originating
585
- // screen + platform + app version. All optional; omitted when unresolved.
586
- // We send ONLY the new response fact + the sessionId; replay/errors/network
587
- // are NOT re-sent — the read side joins them by sessionId.
588
- const input: EngageResponseInput = Array.isArray(result.answers)
589
- ? {
590
- surveyId: campaign.id,
591
- text: result.reason,
592
- answers: toWireAnswers(result.answers),
593
- deviceId: getDeviceId(),
594
- sessionId: currentSessionId(),
595
- screen: activeScreenRef.current,
596
- platform: currentPlatform(),
597
- appVersion: currentAppVersion(),
598
- }
599
- : {
600
- surveyId: campaign.id,
601
- score: result.score,
602
- text: result.reason,
603
- tags: result.tags,
604
- deviceId: getDeviceId(),
605
- sessionId: currentSessionId(),
606
- screen: activeScreenRef.current,
607
- platform: currentPlatform(),
608
- appVersion: currentAppVersion(),
609
- };
610
-
611
- const drafts = result.attachments ?? [];
612
- if (engage.submitResponseConfirmed) {
613
- // Confirmed lane: awaits real persistence (presign+PUT bytes → response
614
- // POST), reports stages, idempotent on responseId, throws on failure.
615
- await engage.submitResponseConfirmed(input, drafts, {
616
- responseId,
617
- onStage: (stage) => setSubmitStatus({ phase: 'submitting', stage }),
618
- });
619
- } else if (drafts.length > 0 && engage.submitResponseWithAttachments) {
620
- // Fallback (older facade): fire-and-forget — resolves immediately.
621
- engage.submitResponseWithAttachments(input, drafts);
622
- } else {
623
- engage.submitResponse(input);
624
- }
625
- }
626
-
627
- store?.markCompleted(campaign.id);
628
- trackCampaign(campaign, 'completion');
629
- setSubmitStatus({ phase: 'success' });
630
- // Brief success beat, then close + reset.
631
- successTimerRef.current = setTimeout(() => {
632
- setActive(null);
633
- activeScreenRef.current = undefined;
634
- resetSubmit();
635
- }, 1100);
636
- } catch (err) {
637
- logger.warn('[Engage] submit failed:', (err as Error)?.message);
638
- setSubmitStatus({ phase: 'error', message: (err as Error)?.message });
639
- }
640
- }, [engage, trackCampaign, ratingRouting, resetSubmit, emitRatingFunnel]);
641
-
642
- const handleSubmit = useCallback(
643
- (campaign: EngageCampaignConfig, result: EngagePromptResult): void => {
644
- // Guard double-submit: ignore re-fires once a submit is in flight or done.
645
- if (submitCtxRef.current && responseIdRef.current) return;
646
- submitCtxRef.current = { campaign, result };
647
- void runSubmit();
648
- },
649
- [runSubmit],
650
- );
651
-
652
- const closeAfterSubmit = useCallback((): void => {
653
- setActive(null);
654
- activeScreenRef.current = undefined;
655
- resetSubmit();
656
- }, [resetSubmit]);
657
-
658
- const showEngagePrompt = useCallback(
659
- async (options?: ShowEngagePromptOptions): Promise<boolean> => {
660
- const store = storeRef.current;
661
- if (!store) return false;
662
- try {
663
- const config = await engage.fetchConfig(options?.context);
664
- if (!config || !Array.isArray(config.campaigns)) return false;
665
-
666
- const campaign = selectCampaignToRender(config.campaigns, store, {
667
- // A behavioral-trigger fire (`options.trigger`) is type-agnostic:
668
- // the trigger itself selects the campaign, so don't layer the
669
- // NPS-first default on top (it would drop FEEDBACK/CSAT/etc.).
670
- // Manual fires keep the provider default unless overridden.
671
- types: options?.types ?? (options?.trigger ? undefined : types),
672
- screen: options?.screen,
673
- trigger: options?.trigger,
674
- seconds: options?.seconds,
675
- event: options?.event,
676
- action: options?.action,
677
- });
678
- if (!campaign) {
679
- logger.debug('[Engage] no eligible campaign to render');
680
- return false;
681
- }
682
-
683
- // Record the impression up front so throttle counts it even if the
684
- // user backgrounds the app before submitting.
685
- store.recordImpression(campaign.id);
686
- // Emit the §2.5 impression event (P3-e #2) so the dashboard's
687
- // response-rate / completion KPIs have a real denominator — the
688
- // prompt path previously only counted impressions locally.
689
- trackCampaign(campaign, 'impression');
690
- // Rating funnel (CONTRACT §1.1): selection passed the throttle/anti-
691
- // annoyance gate (→ eligible) and we are about to render (→ shown).
692
- if (isRatingType(campaign.type)) {
693
- emitRatingFunnel(campaign, 'rating_prompt_eligible');
694
- emitRatingFunnel(campaign, 'rating_prompt_shown');
695
- }
696
- // Stamp the show-time screen alongside the active campaign so
697
- // handleSubmit can attribute the response to its originating screen.
698
- activeScreenRef.current = options?.screen;
699
- surveyStartedRef.current = null;
700
- trackSurveyStage(campaign, 'shown');
701
- resetSubmit();
702
- setActive(campaign);
703
- return true;
704
- } catch (err) {
705
- logger.warn('[Engage] showEngagePrompt failed:', (err as Error)?.message);
706
- return false;
707
- }
708
- },
709
- [engage, types, trackCampaign, trackSurveyStage, emitRatingFunnel],
710
- );
711
-
712
- // ─── In-app message lifecycle (the second Engage family, §2.4/§2.5) ──────
713
- // Reuses the SAME transport (`trackEvent`), the SAME throttle store, and the
714
- // SAME provider — NOT a parallel provider. Events: impression on show, click
715
- // on CTA tap, completion on a finished tour, dismiss on close/skip.
716
-
717
- const trackInApp = useCallback(
718
- (
719
- message: InAppMessageConfig,
720
- eventType:
721
- | 'impression'
722
- | 'completion'
723
- | 'click'
724
- | 'dismiss'
725
- | 'interaction'
726
- | 'render_degraded'
727
- | 'render_failed'
728
- | 'cta_open_failed',
729
- extraMeta?: Record<string, unknown>,
730
- ): void => {
731
- try {
732
- // A/B attribution (D8/J6): when the active message resolved to an
733
- // experiment arm, tag every lifecycle event with the chosen variant
734
- // via the existing optional `meta` field — NO event-schema change
735
- // (EngageEventUpload already carries `meta`; the backend EngageEvent
736
- // accepts it). Plain (non-experiment) messages send no variant key.
737
- const variant = activeInAppVariantRef.current?.variant;
738
- // [T1] Test-preview tagging: a preview-flagged message stamps
739
- // `previewId` + `isTest` + `source` so (a) the backend CONSUMES the
740
- // matching preview row on the impression and (b) production KPIs
741
- // exclude the traffic. Normal campaign messages omit all of it.
742
- const isPreview = message.preview === true || message.isTest === true;
743
- const meta = {
744
- ...(variant ? { variant } : {}),
745
- // testRunId correlates a specific "Send Test" run to its render/click/
746
- // dismiss in the dashboard; rides the existing meta field (no schema churn).
747
- ...(message.testRunId ? { testRunId: message.testRunId } : {}),
748
- ...(extraMeta ?? {}),
749
- };
750
- engage.trackEvent({
751
- campaignId: message.id,
752
- channel: 'inapp',
753
- type: eventType,
754
- deviceId: getDeviceId(),
755
- ...(message.previewId ? { previewId: message.previewId } : {}),
756
- ...(isPreview ? { isTest: true, source: 'test_preview' } : {}),
757
- ...(variant ? { variantId: variant } : {}),
758
- ...(Object.keys(meta).length > 0 ? { meta } : {}),
759
- });
760
- } catch (err) {
761
- logger.debug('[Engage] in-app trackEvent failed:', (err as Error)?.message);
762
- }
763
- },
764
- [engage],
765
- );
766
-
767
- // [T1] In-app message actually mounted on screen. The impression event IS the test
768
- // ACK to the backend (which consumes the preview row → 'rendered'). We ALSO persist the
769
- // testRunId locally so a cold restart can't re-show it before the ACK is processed
770
- // server-side — the one-shot guarantee survives a flaky/slow network.
771
- const handleInAppShow = useCallback(
772
- (message: InAppMessageConfig): void => {
773
- // A slot can be replaced or degrade to an overlay while the same message
774
- // remains active. Treat that as one mount lifecycle, not two impressions.
775
- if (shownInAppMessageIdRef.current === message.id) return;
776
- shownInAppMessageIdRef.current = message.id;
777
- trackInApp(message, 'impression');
778
- if (message.preview === true || message.isTest === true) {
779
- const runId = message.testRunId ?? message.previewId ?? message.id;
780
- seenTestsRef.current?.markSeen(runId);
781
- // Eager-flush so the backend consumes the one-shot preview row NOW — a fast
782
- // close→kill→reopen must not re-serve a still-`delivered` test.
783
- engage.flushEvents?.();
784
- logger.debug(`[Engage] test ${runId} render displayed — ACK sent (impression), flushed`);
785
- }
786
- },
787
- [trackInApp, engage],
788
- );
789
-
790
- const finalizeInAppMessage = useCallback((eventType: 'dismiss' | 'completion'): void => {
791
- setActiveInApp((current) => {
792
- if (current) {
793
- const isTest = current.preview === true || current.isTest === true;
794
- const runId = current.testRunId ?? current.previewId ?? current.id;
795
- logger.debug(`[Engage] in-app ${eventType}${isTest ? ` (test ${runId})` : ''}`);
796
- trackInApp(current, eventType);
797
- if (isTest) {
798
- consumedPreviewIds.current.add(current.previewId ?? current.id);
799
- seenTestsRef.current?.markSeen(runId);
800
- engage.flushEvents?.();
801
- logger.debug(`[Engage] test ${runId} ${eventType} persisted + ACK flushed`);
802
- } else {
803
- storeRef.current?.markCompleted(current.id);
804
- engage.flushEvents?.();
805
- logger.debug(`[Engage] in-app ${current.id} ${eventType} — marked done on device`);
806
- }
807
- }
808
- return null;
809
- });
810
- // Clear the resolved A/B arm after the lifecycle event has read it.
811
- shownInAppMessageIdRef.current = null;
812
- activeInAppVariantRef.current = null;
813
- }, [trackInApp, engage]);
814
-
815
- const dismissInAppMessage = useCallback((): void => {
816
- finalizeInAppMessage('dismiss');
817
- }, [finalizeInAppMessage]);
818
-
819
- const completeInAppMessage = useCallback((): void => {
820
- finalizeInAppMessage('completion');
821
- }, [finalizeInAppMessage]);
822
-
823
- const handleInAppCta = useCallback(
824
- (message: InAppMessageConfig, cta: NonNullable<InAppRenderSpec['cta']>): void => {
825
- if (shouldTrackInAppCta(cta)) trackInApp(message, 'click');
826
- // Deep-link opening is the host's job — surface it, never open it here.
827
- if (cta.action === 'link') {
828
- if (!cta.deepLink) {
829
- // Misconfigured link CTA (no deepLink) — observable, not silent (T1 G17).
830
- logger.warn('[Engage] link CTA has no deepLink');
831
- trackInApp(message, 'cta_open_failed', { reason: 'missing_deeplink' });
832
- } else if (!onInAppDeepLink) {
833
- // Host wired no deep-link sink — the link can't open. Diagnose it.
834
- logger.warn('[Engage] link CTA but no onInAppDeepLink handler supplied');
835
- trackInApp(message, 'cta_open_failed', { reason: 'no_handler' });
836
- } else {
837
- try {
838
- onInAppDeepLink({ message, cta, deepLink: cta.deepLink });
839
- } catch (err) {
840
- logger.warn('[Engage] onInAppDeepLink threw:', (err as Error)?.message);
841
- trackInApp(message, 'cta_open_failed', {
842
- reason: (err as Error)?.message ?? 'handler_threw',
843
- });
844
- }
845
- }
846
- }
847
- // A test preview the user acted on is done — don't re-show it next poll AND
848
- // persist it durably (a CTA tap is as final as a close), then flush the ACK.
849
- if (message.preview === true || message.isTest === true) {
850
- const runId = message.testRunId ?? message.previewId ?? message.id;
851
- consumedPreviewIds.current.add(message.previewId ?? message.id);
852
- seenTestsRef.current?.markSeen(runId);
853
- engage.flushEvents?.();
854
- logger.debug(`[Engage] test ${runId} CTA — persisted locally + ACK flushed`);
855
- } else {
856
- // Production message: a CTA tap is as final as a close — don't re-show it.
857
- storeRef.current?.markCompleted(message.id);
858
- engage.flushEvents?.();
859
- logger.debug(`[Engage] in-app ${message.id} CTA tapped — marked done on device`);
860
- }
861
- setActiveInApp(null);
862
- // Any enabled click event above already read the arm; clear it now.
863
- shownInAppMessageIdRef.current = null;
864
- activeInAppVariantRef.current = null;
865
- },
866
- [trackInApp, onInAppDeepLink, engage],
867
- );
868
-
869
- // [T1] Pick the ONE test preview to render from a fetched config: drop any already
870
- // displayed (persistent seen store) or closed-this-session, then take the LATEST by
871
- // createdAt. One-shot + latest-only is what stops the "tests stack up 1,2,3…" bug.
872
- const pickLatestPreview = useCallback(
873
- (messages: InAppMessageConfig[]): InAppMessageConfig | null => {
874
- const latest = selectLatestUnseenTest(messages, {
875
- seen: (runId) => seenTestsRef.current?.has(runId) ?? false,
876
- consumed: (key) => consumedPreviewIds.current.has(key),
877
- });
878
- if (latest) logger.debug(`[Engage] selected latest test ${testRunIdOf(latest)}`);
879
- return latest;
880
- },
881
- [],
882
- );
883
-
884
- // [T1] Render a test preview IMMEDIATELY — bypassing trigger/throttle/schedule/
885
- // sample/variant. No throttle write (a preview must stay re-showable until it is
886
- // actually rendered + its impression consumes it server-side). Idempotent: if this
887
- // exact preview is already on screen, don't re-mount (avoids a duplicate impression).
888
- const showPreview = useCallback(
889
- (preview: InAppMessageConfig): boolean => {
890
- // PRECEDENCE: a campaign prompt owns the screen — defer (the backend re-serves
891
- // the preview on every poll until TTL, so the next foreground retries).
892
- if (active !== null) {
893
- logger.debug('[Engage] campaign prompt active — preview deferred');
894
- return false;
895
- }
896
- if (activeInApp?.id === preview.id) return true;
897
- const runId = preview.testRunId ?? preview.previewId ?? preview.id;
898
- // Already closed this preview this session — don't re-show on the next poll.
899
- if (consumedPreviewIds.current.has(preview.previewId ?? preview.id)) {
900
- return false;
901
- }
902
- // [T1] One-shot: already DISPLAYED on this device (persisted across restarts) —
903
- // never re-show, even if the backend briefly re-serves a not-yet-ACKed row.
904
- if (seenTestsRef.current?.has(runId)) {
905
- logger.debug(`[Engage] test ${runId} already displayed on device — skip`);
906
- return false;
907
- }
908
- activeInAppVariantRef.current = null;
909
- setActiveInApp(preview);
910
- logger.debug(`[Engage] test ${runId} render started`);
911
- return true;
912
- },
913
- [active, activeInApp],
914
- );
915
-
916
- const showInAppMessage = useCallback(
917
- async (options?: ShowInAppMessageOptions): Promise<boolean> => {
918
- const store = storeRef.current;
919
- if (!store) return false;
920
- // PRECEDENCE: a campaign prompt on screen wins — never stack an in-app
921
- // message over an open survey/NPS/rating prompt.
922
- if (active !== null) {
923
- logger.debug('[Engage] campaign prompt active — in-app message deferred');
924
- return false;
925
- }
926
- try {
927
- const config = await engage.fetchConfig(buildConfigContext(engage, options?.context));
928
- if (!config || !Array.isArray(config.inAppMessages)) return false;
929
-
930
- // [T1] A queued test preview wins immediately, bypassing throttle/variant.
931
- // Pick the LATEST unseen one (one-shot dedupe) — never stack old tests.
932
- const preview = pickLatestPreview(config.inAppMessages);
933
- if (preview) return showPreview(preview);
934
-
935
- // Normal selection runs over NON-preview messages only — a preview must
936
- // never enter the throttle store (it would falsely cap a real campaign id).
937
- const normal = config.inAppMessages.filter(
938
- (m) => !(m.preview === true || m.isTest === true),
939
- );
940
- const message = selectInAppToRender(normal, store, {
941
- screen: options?.screen,
942
- trigger: options?.trigger,
943
- seconds: options?.seconds,
944
- event: options?.event,
945
- action: options?.action,
946
- });
947
- if (!message) {
948
- logger.debug('[Engage] no eligible in-app message to render');
949
- return false;
950
- }
951
-
952
- // A/B variant selection (D8/J6): deterministically bucket this
953
- // device into arm A (base spec) or B (experiment.variantB) BEFORE
954
- // showing, so the impression event (and click/dismiss) attribute to
955
- // the arm the user actually saw. Only retained for attribution when
956
- // the message actually carries an enabled experiment; otherwise the
957
- // resolved spec is just the base spec and no variant key is emitted.
958
- const resolved = selectInAppVariant(message, getDeviceId());
959
- activeInAppVariantRef.current = message.experiment?.enabled
960
- ? resolved
961
- : null;
962
- // Record up front so the throttle counts it (impression also emitted
963
- // by the view's onShow → trackEvent for the analytics lane). Pass the
964
- // content revision so an edited campaign starts a fresh cap generation.
965
- store.recordImpression(message.id, Date.now(), message.revision);
966
- setActiveInApp(message);
967
- return true;
968
- } catch (err) {
969
- logger.warn('[Engage] showInAppMessage failed:', (err as Error)?.message);
970
- return false;
971
- }
972
- },
973
- [engage, active, showPreview, pickLatestPreview],
974
- );
975
-
976
- // ─── Cold-start + foreground preview check (T1) ──────────────────────────
977
- // "Send Test → reopen the app → see it immediately, EVERY time": the SDK fetches
978
- // config (deviceId in context, HTTP cache-bypassed) on mount AND on every
979
- // AppState→active, and renders any queued preview at once — no trigger, no throttle,
980
- // no schedule. The backend keeps serving the preview on every poll until its TTL, so
981
- // a tester sees it on each reopen (rendering records lifecycle but does not consume).
982
- const checkForPreview = useCallback(async (): Promise<void> => {
983
- if (active !== null) return;
984
- try {
985
- const config = await engage.fetchConfig(buildConfigContext(engage));
986
- // One-shot + latest-only: render the newest test not already displayed.
987
- const preview = pickLatestPreview(config?.inAppMessages ?? []);
988
- if (preview) showPreview(preview);
989
- } catch (err) {
990
- logger.warn('[Engage] preview check failed:', (err as Error)?.message);
991
- }
992
- }, [engage, active, showPreview, pickLatestPreview]);
993
-
994
- useEffect(() => {
995
- // Drop stale seen-test entries (past TTL) so the persistent set stays bounded.
996
- seenTestsRef.current?.prune();
997
- void checkForPreview();
998
- const onLifecycle = (state: string): void => {
999
- if (state === 'active') void checkForPreview();
1000
- };
1001
- appLifecycle.addListener(onLifecycle);
1002
- return () => appLifecycle.removeListener(onLifecycle);
1003
- }, [checkForPreview]);
1004
-
1005
- // DEV/TEST warm-foreground poll (T1): covers "Send Test while the app is already
1006
- // open" — no background→foreground edge fires, so without this you'd have to switch
1007
- // apps to see it. Only runs when the host opts in via `previewPollMs` (unset in prod).
1008
- useEffect(() => {
1009
- if (!previewPollMs || previewPollMs <= 0) return;
1010
- logger.debug(`[Engage] test-preview warm poll every ${previewPollMs}ms (dev)`);
1011
- const interval = setInterval(() => {
1012
- void checkForPreview();
1013
- }, previewPollMs);
1014
- return () => clearInterval(interval);
1015
- }, [previewPollMs, checkForPreview]);
1016
-
1017
- // ─── Always-on behavioral triggers (P3-e #3 / Slice E) ───────────────────
1018
- // The trigger engine wires every behavioral trigger (session_start, app_open,
1019
- // screen_view/exit, time_in_app, n_sessions, after_purchase, before_logout,
1020
- // custom_event, failed_action, after_crash/js_error, network_error, slow_screen,
1021
- // and the native gesture triggers) to the SDK signals the app already produces.
1022
- // A fire first tries the survey/rating campaign path (showEngagePrompt); if no
1023
- // campaign matches, the SAME trigger drives an in-app message (showInAppMessage).
1024
- // Both families share the throttle store, so a behavioral fire never double-shows.
1025
- // The engine buffers events fired before the first config arrives and replays
1026
- // them once it does (late binding), honoring each trigger's remaining delay.
1027
- useEffect(() => {
1028
- return installEngageTriggerEngine({
1029
- fire: (options) => {
1030
- void (async () => {
1031
- const shown = await showEngagePrompt(options);
1032
- if (!shown && options.trigger) {
1033
- await showInAppMessage({
1034
- trigger: options.trigger,
1035
- screen: options.screen,
1036
- event: options.event,
1037
- action: options.action,
1038
- seconds: options.seconds,
1039
- });
1040
- }
1041
- })();
1042
- },
1043
- fetchConfig: () => engage.fetchConfig(buildConfigContext(engage)),
1044
- });
1045
- }, [showEngagePrompt, showInAppMessage, engage]);
1046
-
1047
- const controller = useMemo<EngagePromptController>(
1048
- () => ({
1049
- showEngagePrompt,
1050
- dismissEngagePrompt,
1051
- showInAppMessage,
1052
- dismissInAppMessage,
1053
- }),
1054
- [showEngagePrompt, dismissEngagePrompt, showInAppMessage, dismissInAppMessage],
1055
- );
1056
-
1057
- const activeInAppSpec = activeInAppVariantRef.current?.spec ?? activeInApp?.spec;
1058
- const activeInAppPresentation = activeInApp && activeInAppSpec
1059
- ? resolveInAppPresentation({
1060
- layout: activeInApp.layout,
1061
- variantKey: activeInApp.variantKey,
1062
- spec: activeInAppSpec,
1063
- })
1064
- : null;
1065
- // Route by the canonical mount, not a variant allow-list. This covers every
1066
- // current/future inline variant, including smart_inbox_message.
1067
- const routesToInlineSlot = activeInAppPresentation?.mountModel === 'inline';
1068
- const inlinePlacement = resolveEngageInlinePlacement(activeInAppSpec);
1069
-
1070
- const handleActiveInAppShow = useCallback((): void => {
1071
- if (!activeInApp) return;
1072
- handleInAppShow(activeInApp);
1073
- const tourId = activeInApp.spec.ext?.coachTourId;
1074
- const first = Array.isArray(activeInApp.spec.ext?.steps) ? activeInApp.spec.ext?.steps[0] as Record<string, unknown> | undefined : undefined;
1075
- if (typeof tourId === 'string') {
1076
- engage.trackCoachmarkEvent?.('$coachmark_tour_started', { tourId });
1077
- engage.trackCoachmarkEvent?.('$coachmark_step_entered', {
1078
- tourId,
1079
- stepId: String(first?.id ?? first?.anchorKey ?? '1'),
1080
- });
1081
- }
1082
- }, [activeInApp, handleInAppShow, engage]);
1083
- const handleActiveInAppCta = useCallback((cta: NonNullable<InAppRenderSpec['cta']>): void => {
1084
- if (activeInApp) handleInAppCta(activeInApp, cta);
1085
- }, [activeInApp, handleInAppCta]);
1086
- const handleActiveInAppInteraction = useCallback((interaction: InAppMechanicInteraction): void => {
1087
- if (!activeInApp) return;
1088
- trackInApp(activeInApp, 'interaction', { interaction });
1089
- const tourId = activeInApp.spec.ext?.coachTourId;
1090
- if (typeof tourId !== 'string' || interaction.mechanic !== 'coachmark_spotlight') return;
1091
- const meta = interaction.meta ?? {};
1092
- const stepId = String(meta.anchorKey ?? meta.step ?? meta.toStep ?? 'unknown');
1093
- if (interaction.result === 'step_viewed' && interaction.phase !== 'started') {
1094
- engage.trackCoachmarkEvent?.('$coachmark_step_entered', { tourId, stepId });
1095
- } else if (interaction.phase === 'completed') {
1096
- engage.trackCoachmarkEvent?.('$coachmark_tour_completed', { tourId, stepId });
1097
- } else if (interaction.result === 'skipped') {
1098
- engage.trackCoachmarkEvent?.('$coachmark_tour_abandoned', { tourId, stepId });
1099
- }
1100
- }, [activeInApp, trackInApp, engage]);
1101
- const handleActiveInAppRenderError = useCallback((reason: string): void => {
1102
- if (activeInApp) {
1103
- trackInApp(activeInApp, 'render_failed', { reason });
1104
- const tourId = activeInApp.spec.ext?.coachTourId;
1105
- if (typeof tourId === 'string') {
1106
- const anchorKey = reason.startsWith('anchor_not_found:') ? reason.slice('anchor_not_found:'.length) : 'unknown';
1107
- engage.trackCoachmarkEvent?.('$coachmark_anchor_failed', {
1108
- tourId,
1109
- stepId: anchorKey,
1110
- reason: reason.startsWith('anchor_not_found:') ? 'anchor_not_found' : reason,
1111
- });
1112
- }
1113
- }
1114
- shownInAppMessageIdRef.current = null;
1115
- activeInAppVariantRef.current = null;
1116
- setActiveInApp(null);
1117
- }, [activeInApp, trackInApp, engage]);
1118
-
1119
- useEffect(() => {
1120
- if (!routesToInlineSlot || !inlinePlacement.placementKey) return;
1121
- return inlinePlacementRegistry.subscribe(inlinePlacement.placementKey, () => {
1122
- setInlinePlacementRevision((revision) => revision + 1);
1123
- });
1124
- }, [inlinePlacement.placementKey, inlinePlacementRegistry, routesToInlineSlot]);
1125
-
1126
- useEffect(() => {
1127
- if (!activeInApp || active !== null || !routesToInlineSlot) {
1128
- setInlineFallbackMessageId(null);
1129
- return;
1130
- }
1131
-
1132
- const messageId = activeInApp.id;
1133
- // Once this message has visibly degraded, keep it on that mount. Moving it
1134
- // into a late slot would create a second renderer and a misleading lifecycle.
1135
- if (inlineFallbackMessageId === messageId) return;
1136
- const reason = inlinePlacement.placementKey
1137
- ? `inline_placement_not_found:${inlinePlacement.placementKey}`
1138
- : 'missing_inline_placement_key';
1139
- const delivery: EngageInlineDelivery = {
1140
- message: activeInApp,
1141
- spec: activeInAppSpec,
1142
- onShow: handleActiveInAppShow,
1143
- onCta: handleActiveInAppCta,
1144
- onDismiss: dismissInAppMessage,
1145
- onComplete: completeInAppMessage,
1146
- onInteraction: handleActiveInAppInteraction,
1147
- onInAppGameRequest,
1148
- onRenderError: handleActiveInAppRenderError,
1149
- };
1150
- const delivered = inlinePlacementRegistry.deliver(
1151
- inlinePlacement.placementKey,
1152
- delivery,
1153
- );
1154
-
1155
- if (delivered) {
1156
- setInlineFallbackMessageId(null);
1157
- } else {
1158
- inlinePlacementRegistry.clear(inlinePlacement.placementKey, messageId);
1159
- if (inlinePlacement.fallback === 'skip') {
1160
- setInlineFallbackMessageId(null);
1161
- handleActiveInAppRenderError(reason);
1162
- } else {
1163
- // Preserve the legacy visible behavior, but make the degradation observable.
1164
- trackInApp(activeInApp, 'render_degraded', {
1165
- reason,
1166
- placementKey: inlinePlacement.placementKey,
1167
- fallback: 'overlay',
1168
- });
1169
- setInlineFallbackMessageId(messageId);
1170
- }
1171
- }
1172
-
1173
- return () => inlinePlacementRegistry.clear(inlinePlacement.placementKey, messageId);
1174
- }, [
1175
- active,
1176
- activeInApp,
1177
- activeInAppSpec,
1178
- dismissInAppMessage,
1179
- completeInAppMessage,
1180
- handleActiveInAppCta,
1181
- handleActiveInAppInteraction,
1182
- handleActiveInAppRenderError,
1183
- handleActiveInAppShow,
1184
- inlinePlacement.fallback,
1185
- inlinePlacement.placementKey,
1186
- inlinePlacementRegistry,
1187
- inlineFallbackMessageId,
1188
- inlinePlacementRevision,
1189
- onInAppGameRequest,
1190
- routesToInlineSlot,
1191
- trackInApp,
1192
- ]);
1193
-
1194
- const rootInAppVisible = activeInApp !== null &&
1195
- active === null &&
1196
- (!routesToInlineSlot || inlineFallbackMessageId === activeInApp.id);
1197
-
1198
- return (
1199
- <EngageAnchorProvider>
1200
- <EngageInlinePlacementProvider registry={inlinePlacementRegistry}>
1201
- <EngagePromptContext.Provider value={controller}>
1202
- {children}
1203
- <EngagePromptView
1204
- campaign={active}
1205
- visible={active !== null}
1206
- rating={ratingRouting}
1207
- submitStatus={submitStatus}
1208
- onRetrySubmit={() => void runSubmit()}
1209
- onCloseSubmit={closeAfterSubmit}
1210
- onSubmit={(result) => {
1211
- if (active) handleSubmit(active, result);
1212
- }}
1213
- onStart={() => {
1214
- if (active && surveyStartedRef.current !== active.id) {
1215
- surveyStartedRef.current = active.id;
1216
- trackSurveyStage(active, 'started');
1217
- }
1218
- }}
1219
- onDismiss={dismissEngagePrompt}
1220
- />
1221
- {/* In-app message overlay. PRECEDENCE: only visible when no campaign
1222
- prompt is on screen, so the two families never fight for the view. */}
1223
- <EngageInAppView
1224
- message={activeInApp}
1225
- visible={rootInAppVisible}
1226
- mountModelOverride={routesToInlineSlot && inlineFallbackMessageId === activeInApp?.id
1227
- ? 'overlay'
1228
- : undefined}
1229
- // Render the resolved A/B arm's content (D8/J6) when an experiment is
1230
- // active; undefined ⇒ the view falls back to the message's base spec.
1231
- spec={activeInAppVariantRef.current?.spec}
1232
- onShow={handleActiveInAppShow}
1233
- onCta={handleActiveInAppCta}
1234
- onDismiss={dismissInAppMessage}
1235
- onComplete={completeInAppMessage}
1236
- onInteraction={handleActiveInAppInteraction}
1237
- onInAppGameRequest={onInAppGameRequest}
1238
- onRenderError={handleActiveInAppRenderError}
1239
- />
1240
- </EngagePromptContext.Provider>
1241
- </EngageInlinePlacementProvider>
1242
- </EngageAnchorProvider>
1243
- );
1244
- }
1245
-
1246
- /**
1247
- * Hook a host app uses to trigger/dismiss the prompt:
1248
- * const { showEngagePrompt } = useEngagePrompt();
1249
- * showEngagePrompt({ types: ['NPS'] });
1250
- */
1251
- export function useEngagePrompt(): EngagePromptController {
1252
- const ctx = useContext(EngagePromptContext);
1253
- if (!ctx) {
1254
- // Fail-soft: a host that calls the hook outside the provider gets no-ops
1255
- // instead of a crash (matches the SDK's no-throw public-API style).
1256
- return {
1257
- showEngagePrompt: async () => {
1258
- logger.warn('[Engage] useEngagePrompt() called outside <EngagePromptProvider>');
1259
- return false;
1260
- },
1261
- dismissEngagePrompt: () => {},
1262
- showInAppMessage: async () => {
1263
- logger.warn('[Engage] useEngagePrompt() called outside <EngagePromptProvider>');
1264
- return false;
1265
- },
1266
- dismissInAppMessage: () => {},
1267
- };
1268
- }
1269
- return ctx;
1270
- }
1
+ /**
2
+ * ScaleBun SDK — Engage Prompt Provider (campaign renderer core, D4)
3
+ *
4
+ * Wraps the host app and owns the campaign-render lifecycle for the shared
5
+ * cross-platform JS overlay:
6
+ * 1. on a trigger (app-controlled via `showEngagePrompt()` and/or the campaign's
7
+ * own `trigger` from config), calls `facade.engage.fetchConfig()`,
8
+ * 2. runs the throttle/decision core (`selectCampaignToRender`) to pick which
9
+ * campaign — if any — is eligible, honoring frequency caps,
10
+ * 3. mounts the parameterized `EngagePromptView` (Open/Closed: NPS now,
11
+ * ratings/feedback/survey later via the renderer registry),
12
+ * 4. on submit → `facade.engage.submitResponse({ surveyId, score, text })`
13
+ * (transport stamps `responseId` UUID + `schemaVersion` per contract),
14
+ * records the impression as completed, and emits an in-app dismiss/submit
15
+ * tracking event,
16
+ * 5. on dismiss → `facade.engage.trackEvent` with a `dismiss` event.
17
+ *
18
+ * The provider depends only on the `engage` namespace shape — NOT the whole
19
+ * facade — so it stays decoupled and testable, and reuses the existing transport
20
+ * (no second HTTP path).
21
+ *
22
+ * IN-APP MESSAGES (the second Engage family, §2.4/§2.5) are surfaced by this SAME
23
+ * provider — NOT a parallel one. `showInAppMessage()` fetches the config, picks an
24
+ * eligible message from `inAppMessages[]` (shared throttle store), and mounts the
25
+ * config-driven `EngageInAppView` (banner/modal/overlay). Events: `impression` on
26
+ * show, `click` on CTA tap (the resolved deep link is surfaced to the host via
27
+ * `onInAppDeepLink` — the SDK never opens URLs), `dismiss` on close.
28
+ *
29
+ * PRECEDENCE (campaign vs in-app): a campaign prompt wins the screen. If a
30
+ * campaign prompt is already visible, `showInAppMessage()` is a no-op (returns
31
+ * false) and the mounted in-app view is hidden while a campaign is up, so the two
32
+ * families never fight for the screen.
33
+ */
34
+
35
+ import React, {
36
+ createContext,
37
+ useContext,
38
+ useCallback,
39
+ useEffect,
40
+ useMemo,
41
+ useRef,
42
+ useState,
43
+ type ReactNode,
44
+ type ReactElement,
45
+ } from 'react';
46
+ import { Linking, Platform } from 'react-native';
47
+ import { logger } from '../../core/logger/internalLogger';
48
+ import { installEngageTriggerEngine } from './engageTriggerEngine';
49
+ import { appLifecycle } from '../../core/lifecycle/appLifecycle';
50
+ import { getDeviceId } from '../../core/id/deviceId';
51
+ import { ReplaySdk } from '../replay/public/api';
52
+ import { SessionManager } from '../session/SessionManager';
53
+ import {
54
+ EngagePromptView,
55
+ type EngagePromptResult,
56
+ type EngageSubmitStatus,
57
+ type RatingPromptConfig,
58
+ } from './EngagePromptView';
59
+ import { EngageInAppView, type InAppMechanicInteraction } from './EngageInAppView';
60
+ import { EngageAnchorProvider } from './EngageAnchor';
61
+ import {
62
+ EngageInlinePlacementProvider,
63
+ createEngageInlinePlacementRegistry,
64
+ resolveEngageInlinePlacement,
65
+ type EngageInlineDelivery,
66
+ } from './EngageInlinePlacement';
67
+ import { resolveInAppPresentation } from './engageVariantResolver';
68
+ import { shouldTrackInAppCta } from './engageOutcome';
69
+ import type { SubmitStage } from './EngageTransport';
70
+ import {
71
+ EngageThrottleStore,
72
+ selectCampaignToRender,
73
+ selectInAppToRender,
74
+ selectInAppVariant,
75
+ selectLatestUnseenTest,
76
+ testRunIdOf,
77
+ } from './engageThrottle';
78
+ import { EngageTestSeenStore } from './engageTestSeenStore';
79
+ import type {
80
+ EngageAttachmentDraft,
81
+ EngageCampaignConfig,
82
+ EngageCampaignType,
83
+ EngageConfigContext,
84
+ EngageConfigResponse,
85
+ EngageEventInput,
86
+ InAppGameRequestHandler,
87
+ EngageResponseInput,
88
+ InAppMessageConfig,
89
+ InAppRenderSpec,
90
+ InAppVariantId,
91
+ RatingFunnelEventDims,
92
+ RatingFunnelEventInput,
93
+ RatingFunnelEventType,
94
+ SurveyAnswer,
95
+ SurveyImpressionInput,
96
+ } from './engageTypes';
97
+
98
+ /** Client-generated UUID for app-rating idempotency (D8: `clientRatingId`). */
99
+ function ratingUuid(): string {
100
+ return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {
101
+ const r = (Math.random() * 16) | 0;
102
+ const v = c === 'x' ? r : (r & 0x3) | 0x8;
103
+ return v.toString(16);
104
+ });
105
+ }
106
+
107
+ /** Preserve a multi-question survey answer in the keyed wire shape (§1.4). */
108
+ export function toWireAnswers(
109
+ answers: SurveyAnswer[],
110
+ ): { key: string; value: string | number | string[] }[] {
111
+ return answers.map((a) => ({
112
+ key: a.key,
113
+ value: a.value,
114
+ }));
115
+ }
116
+
117
+ /**
118
+ * Resolve the canonical session id for response linkage (contract §1/§7).
119
+ * Primary source is `SessionManager.currentSessionId` — the always-on analytics
120
+ * session id (`rs-…`) that the replay recording attaches to (and that `/sessions/:id`
121
+ * keys on). `ReplaySdk.sessionId` (the orchestrator's recording id) is only set
122
+ * while a recording is mid-flight and reads `null` at submit time, so it is a
123
+ * fallback, not the primary. Returns `undefined` (not `null`) so the optional wire
124
+ * field is simply omitted when no session is active.
125
+ */
126
+ function currentSessionId(): string | undefined {
127
+ return (
128
+ SessionManager.getExistingInstance()?.currentSessionId ??
129
+ ReplaySdk.sessionId ??
130
+ undefined
131
+ );
132
+ }
133
+
134
+ /**
135
+ * The host app version for by-version analytics (contract §1). Read from the
136
+ * SAME synchronous source the SDK's rating lane already uses
137
+ * (`SessionManager.currentSessionMetadata.appVersion`, populated from native
138
+ * device info) — NOT hardcoded, and NOT the SDK build version. `undefined` when
139
+ * no session metadata is available yet, so the optional field is omitted.
140
+ */
141
+ function currentAppVersion(): string | undefined {
142
+ return SessionManager.getExistingInstance()?.currentSessionMetadata?.appVersion ?? undefined;
143
+ }
144
+
145
+ /**
146
+ * Device platform as the `'android' | 'ios'` wire union (contract §1). Shared JS
147
+ * path — NOT platform-gated — so Android and iOS both stamp their own value.
148
+ * `Platform.OS` also yields `'windows' | 'macos' | 'web'`; those are out of the
149
+ * SDK's mobile scope and intentionally collapse to `undefined` (field omitted).
150
+ */
151
+ function currentPlatform(): 'android' | 'ios' | undefined {
152
+ return Platform.OS === 'android' || Platform.OS === 'ios' ? Platform.OS : undefined;
153
+ }
154
+
155
+ /**
156
+ * Build the config-serve context (contract §1.3 query). ALWAYS carries `deviceId`
157
+ * — the backend keys per-device test previews on it, so omitting it would hide a
158
+ * "Send Test" preview from the very device it was queued for (T1). `platform`/
159
+ * `appVersion` ride along for server-side targeting; both honest, both omitted when
160
+ * unresolved. A caller-supplied `context` (manual show) overrides field-by-field.
161
+ */
162
+ function buildConfigContext(
163
+ engage: EngageRendererFacade,
164
+ override?: EngageConfigContext,
165
+ ): EngageConfigContext {
166
+ const identifiedUserId = engage.getIdentifiedUserId?.();
167
+ return {
168
+ deviceId: getDeviceId(),
169
+ ...(currentPlatform() ? { platform: currentPlatform() } : {}),
170
+ ...(currentAppVersion() ? { appVersion: currentAppVersion() } : {}),
171
+ ...(identifiedUserId ? { endUserId: identifiedUserId } : {}),
172
+ ...override,
173
+ };
174
+ }
175
+
176
+ /**
177
+ * Build the rating-funnel breakdown dimensions (ratings-rebuild CONTRACT §1.2 `dims`)
178
+ * from the SAME live session metadata the response builder reads — NOT hardcoded.
179
+ * Only honest, present values are included; `country`/`locale`/`acquisitionSource`
180
+ * are intentionally omitted here (no on-device source yet) so the backend reports
181
+ * them as absent rather than fabricated.
182
+ */
183
+ function currentRatingDims(): RatingFunnelEventDims {
184
+ const meta = SessionManager.getExistingInstance()?.currentSessionMetadata;
185
+ const platform = currentPlatform();
186
+ return {
187
+ ...(platform ? { platform } : {}),
188
+ ...(meta?.appVersion ? { appVersion: meta.appVersion } : {}),
189
+ ...(meta?.osVersion ? { osVersion: meta.osVersion } : {}),
190
+ ...(meta?.deviceModel ? { deviceModel: meta.deviceModel } : {}),
191
+ };
192
+ }
193
+
194
+ /**
195
+ * The slice of the SDK facade the renderer consumes (the `engage` namespace).
196
+ * Matching this shape — rather than importing the facade — keeps the renderer a
197
+ * pure consumer of the foundation transport and trivially testable.
198
+ */
199
+ export interface EngageRendererFacade {
200
+ /** External user id last supplied through ScaleBun.identify(). */
201
+ getIdentifiedUserId?: () => string | undefined;
202
+ fetchConfig: (context?: EngageConfigContext) => Promise<EngageConfigResponse | null>;
203
+ trackCoachmarkEvent?: (name: string, properties: Record<string, unknown>) => void;
204
+ submitResponse: (input: EngageResponseInput) => void;
205
+ /**
206
+ * [P3-e] Submit a response with native attachments (screenshot/voice). Optional
207
+ * so a host wired to an older facade still renders prompts (media silently
208
+ * degrades to a plain response).
209
+ */
210
+ submitResponseWithAttachments?: (
211
+ input: EngageResponseInput,
212
+ attachments: EngageAttachmentDraft[],
213
+ ) => void;
214
+ /**
215
+ * [Slice D5] CONFIRMED submit used by the reusable submitting→success→error state
216
+ * machine: resolves only on real server persistence, rejects on failure, idempotent
217
+ * on `responseId`. Optional so an older facade still renders prompts (falls back to
218
+ * the fire-and-forget lanes, which resolve immediately).
219
+ */
220
+ submitResponseConfirmed?: (
221
+ input: EngageResponseInput,
222
+ attachments: EngageAttachmentDraft[],
223
+ opts: { responseId: string; onStage?: (stage: SubmitStage) => void },
224
+ ) => Promise<void>;
225
+ trackEvent: (input: EngageEventInput) => void;
226
+ trackSurveyImpression?: (input: SurveyImpressionInput) => void;
227
+ /**
228
+ * Force-flush queued in-app events immediately (bypassing the batch threshold/timer).
229
+ * Called right after a TEST preview's impression/dismiss ACK so the backend consumes
230
+ * the one-shot preview row before the app can be backgrounded/killed — otherwise a
231
+ * still-`delivered` row re-serves on the next reopen. Optional: an older facade simply
232
+ * relies on the periodic flush (eventual consistency).
233
+ */
234
+ flushEvents?: () => void;
235
+ /**
236
+ * Submit a 1–5 app-store rating via the EXISTING rating lane (NOT
237
+ * submitResponse — D1 keeps app-ratings a distinct funnel). The provider
238
+ * passes a client `clientRatingId` for idempotency (D8). Optional so a host
239
+ * that never shows RATING_PROMPT need not supply it.
240
+ */
241
+ submitRating?: (input: {
242
+ rating: number;
243
+ comment?: string;
244
+ source?: 'in_app' | 'prompt' | 'manual';
245
+ clientRatingId?: string;
246
+ }) => unknown;
247
+ /**
248
+ * Emit a rating-funnel tracking fact (ratings-rebuild CONTRACT §1.2) — eligible/
249
+ * shown/dismissed/selected/redirect. NOT a campaign response (D1). Optional so an
250
+ * older facade still renders rating prompts (the funnel just goes uninstrumented).
251
+ */
252
+ emitRatingEvent?: (input: RatingFunnelEventInput) => void;
253
+ /**
254
+ * Trigger the native in-app review sheet (D5). Resolves `true` only when the OS
255
+ * flow ran/resolved after a positive route, so the provider emits
256
+ * `store_redirect_clicked` solely on a `true` result. Optional/fail-soft.
257
+ */
258
+ requestStoreReview?: () => Promise<boolean>;
259
+ }
260
+
261
+ /**
262
+ * Host-app RATING_PROMPT routing config. The store deeplink is NEVER hardcoded —
263
+ * the host supplies either a static `storeUrl` or an `onHighRating` callback (e.g.
264
+ * `Linking.openURL(...)` / native `requestReview()`), and an `onLowRating` for the
265
+ * feedback hand-off. The provider only decides WHICH callback to invoke.
266
+ */
267
+ export interface EngageRatingRouting extends RatingPromptConfig {
268
+ /** App-store deeplink opened on a high rating (host owns the navigation). */
269
+ storeUrl?: string;
270
+ /** Called on a high rating (>= threshold). Receives the resolved store URL if set. */
271
+ onHighRating?: (info: { rating: number; campaign: EngageCampaignConfig; storeUrl?: string }) => void;
272
+ /** Called on a low rating when routing to feedback (host opens its form). */
273
+ onLowRating?: (info: { rating: number; campaign: EngageCampaignConfig }) => void;
274
+ }
275
+
276
+ export interface ShowEngagePromptOptions {
277
+ /** Restrict to specific campaign types. Defaults to `['NPS']` (NPS-first slice). */
278
+ types?: EngageCampaignType[];
279
+ /** Match a campaign's `targetScreen` to the current screen. */
280
+ screen?: string;
281
+ /**
282
+ * Restrict to campaigns whose `trigger` equals this value (behavioral-trigger
283
+ * path, e.g. `'screen_exit'`). Omitted ⇒ trigger-agnostic (manual fire).
284
+ */
285
+ trigger?: string;
286
+ /** Event name for `custom_event` / `after_purchase` (matches `triggerConfig.event`). */
287
+ event?: string;
288
+ /** Action label for `failed_action` (matches `triggerConfig.action`). */
289
+ action?: string;
290
+ /** Fired `time_in_app` threshold, used to select only that configured timer. */
291
+ seconds?: number;
292
+ /** App/user context forwarded to the config fetch for server-side targeting. */
293
+ context?: EngageConfigContext;
294
+ }
295
+
296
+ export interface ShowInAppMessageOptions {
297
+ /** Match a message's `targetScreen` to the current screen. */
298
+ screen?: string;
299
+ /**
300
+ * Restrict to messages whose `trigger` equals this value (behavioral-trigger
301
+ * path, e.g. `'session_start'`). Omitted ⇒ trigger-agnostic (manual host call).
302
+ */
303
+ trigger?: string;
304
+ /** Fired business/custom event name, matched against `message.eventName`. */
305
+ event?: string;
306
+ /** Fired action value for forward-compatible action-specific messages. */
307
+ action?: string;
308
+ /** Fired `time_delay` threshold, used to select only that configured message. */
309
+ seconds?: number;
310
+ /** App/user context forwarded to the config fetch for server-side targeting. */
311
+ context?: EngageConfigContext;
312
+ }
313
+
314
+ /**
315
+ * The host's deep-link sink for an in-app CTA tap. The SDK NEVER opens a URL — it
316
+ * hands the resolved `deepLink` (and full message/cta) to the host, which decides
317
+ * how to navigate (e.g. `Linking.openURL` / a router push). Only fired for a CTA
318
+ * whose `action` resolves to a link with a `deepLink`.
319
+ */
320
+ export type InAppDeepLinkHandler = (info: {
321
+ message: InAppMessageConfig;
322
+ cta: NonNullable<InAppRenderSpec['cta']>;
323
+ deepLink: string;
324
+ }) => void;
325
+
326
+ /** Imperative controller a host app uses to trigger a prompt / in-app message. */
327
+ export interface EngagePromptController {
328
+ /** Fetch config, pick an eligible campaign, and show it. Returns whether one was shown. */
329
+ showEngagePrompt: (options?: ShowEngagePromptOptions) => Promise<boolean>;
330
+ /** Dismiss the currently visible prompt (no response submitted). */
331
+ dismissEngagePrompt: () => void;
332
+ /**
333
+ * Fetch config, pick an eligible in-app message (`inAppMessages[]`), and show
334
+ * it. Returns whether one was shown. PRECEDENCE: a campaign prompt already on
335
+ * screen wins — an in-app message is NOT shown over it (see provider doc).
336
+ */
337
+ showInAppMessage: (options?: ShowInAppMessageOptions) => Promise<boolean>;
338
+ /** Dismiss the currently visible in-app message (emits a `dismiss` event). */
339
+ dismissInAppMessage: () => void;
340
+ }
341
+
342
+ const EngagePromptContext = createContext<EngagePromptController | null>(null);
343
+
344
+ export interface EngagePromptProviderProps {
345
+ /** The SDK facade's `engage` namespace (e.g. `ScaleBun.engage`). */
346
+ engage: EngageRendererFacade;
347
+ /** Default campaign types to consider. Defaults to NPS-first. */
348
+ defaultTypes?: EngageCampaignType[];
349
+ /**
350
+ * RATING_PROMPT routing config (host-supplied). The app-store deeplink and
351
+ * feedback hand-off are NEVER hardcoded in the SDK — supplied here.
352
+ */
353
+ ratingRouting?: EngageRatingRouting;
354
+ /**
355
+ * Host sink for an in-app message CTA deep link. The SDK never opens URLs —
356
+ * it surfaces the resolved `deepLink` here for the host to navigate. Optional:
357
+ * a host that never uses link-action CTAs need not supply it.
358
+ */
359
+ onInAppDeepLink?: InAppDeepLinkHandler;
360
+ /**
361
+ * Required when a production gamified campaign is used. The SDK calls this
362
+ * only at play/load/check-in/quiz resolution time; the host's authenticated
363
+ * backend owns eligibility, granting, and the returned result.
364
+ */
365
+ onInAppGameRequest?: InAppGameRequestHandler;
366
+ /**
367
+ * DEV/TEST ONLY — poll interval (ms) for queued test previews while the app is
368
+ * already foregrounded. `checkForPreview` runs on mount + every AppState→active,
369
+ * which covers "reopen the app". But if you press "Send Test" while the app is
370
+ * ALREADY open and in the foreground, there is no background→foreground edge to
371
+ * trigger a refetch. Setting e.g. `previewPollMs={4000}` makes a warm, foreground
372
+ * app pick up a Send Test within a few seconds with no app switch. Leave UNSET in
373
+ * production (0/undefined ⇒ no polling — the foreground/cold-start fetch is enough).
374
+ */
375
+ previewPollMs?: number;
376
+ children: ReactNode;
377
+ }
378
+
379
+ const DEFAULT_TYPES: EngageCampaignType[] = ['NPS'];
380
+
381
+ /**
382
+ * Provider that mounts the shared overlay and exposes the imperative controller
383
+ * via `useEngagePrompt()`.
384
+ */
385
+ export function EngagePromptProvider({
386
+ engage,
387
+ defaultTypes,
388
+ ratingRouting,
389
+ onInAppDeepLink,
390
+ onInAppGameRequest,
391
+ previewPollMs,
392
+ children,
393
+ }: EngagePromptProviderProps): ReactElement {
394
+ const [active, setActive] = useState<EngageCampaignConfig | null>(null);
395
+ const [activeInApp, setActiveInApp] = useState<InAppMessageConfig | null>(null);
396
+ const [inlineFallbackMessageId, setInlineFallbackMessageId] = useState<string | null>(null);
397
+ const [inlinePlacementRevision, setInlinePlacementRevision] = useState(0);
398
+ const inlinePlacementRegistry = useMemo(createEngageInlinePlacementRegistry, []);
399
+ const shownInAppMessageIdRef = useRef<string | null>(null);
400
+ // Resolved A/B arm for the active in-app message (D8/J6). Held in a ref: it is
401
+ // render-stable metadata (the chosen `spec` drives the view, the `variant` id
402
+ // rides the lifecycle events) and must not perturb the precedence that keys off
403
+ // `activeInApp`. `null` when no message is active (or it has no experiment).
404
+ const activeInAppVariantRef = useRef<
405
+ { variant: InAppVariantId; spec: InAppRenderSpec } | null
406
+ >(null);
407
+ // Show-time screen of the currently-active campaign prompt (contract §1
408
+ // `screen`). Held in a ref alongside `active` — it is render-irrelevant
409
+ // metadata read only at submit, so it needs no re-render and must not perturb
410
+ // the campaign-vs-in-app precedence which keys off `active`/`activeInApp`.
411
+ const activeScreenRef = useRef<string | undefined>(undefined);
412
+ const surveyStartedRef = useRef<string | null>(null);
413
+ // [T1] Test previews bypass the throttle store and the backend re-serves them on
414
+ // EVERY config poll until TTL — great for "reopen the app and see it again", but it
415
+ // means a dismissed preview would re-appear on the next warm poll. This session set
416
+ // records previews the user already closed (dismiss/CTA) so we don't re-show the SAME
417
+ // one. It is in-memory only: a cold restart clears it, so reopening the app still
418
+ // shows the queued test (the intended QA behavior).
419
+ const consumedPreviewIds = useRef<Set<string>>(new Set());
420
+ // [T1] Persistent dedupe for ONE-SHOT test delivery — survives cold restarts (unlike
421
+ // consumedPreviewIds above). A testRunId is recorded here AFTER it actually renders, so
422
+ // reopening the app does NOT re-show a test the device already displayed. This is the
423
+ // fix for "close/open and the old test re-appears, and they stack up". Separate from the
424
+ // throttle store so production frequency caps never block a fresh test and vice-versa.
425
+ const seenTestsRef = useRef<EngageTestSeenStore | null>(null);
426
+ if (seenTestsRef.current === null) {
427
+ seenTestsRef.current = new EngageTestSeenStore();
428
+ }
429
+ // One persistent throttle store for the provider lifetime — SHARED by campaigns
430
+ // and in-app messages so both honor the same per-id frequency caps.
431
+ const storeRef = useRef<EngageThrottleStore | null>(null);
432
+ if (storeRef.current === null) {
433
+ storeRef.current = new EngageThrottleStore();
434
+ }
435
+ const types = defaultTypes ?? DEFAULT_TYPES;
436
+
437
+ // ─── Reusable submit state machine (Slice D5) ────────────────────────────
438
+ // ONE machine for EVERY question type. `responseIdRef` is the idempotency key,
439
+ // generated once per prompt and REUSED on retry so a re-send can't duplicate.
440
+ // `submitCtxRef` holds the campaign+result so retry re-runs the same submit.
441
+ const [submitStatus, setSubmitStatus] = useState<EngageSubmitStatus>({ phase: 'idle' });
442
+ const responseIdRef = useRef<string | null>(null);
443
+ const submitCtxRef = useRef<{ campaign: EngageCampaignConfig; result: EngagePromptResult } | null>(null);
444
+ const successTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);
445
+
446
+ const resetSubmit = useCallback((): void => {
447
+ if (successTimerRef.current) {
448
+ clearTimeout(successTimerRef.current);
449
+ successTimerRef.current = null;
450
+ }
451
+ responseIdRef.current = null;
452
+ submitCtxRef.current = null;
453
+ setSubmitStatus({ phase: 'idle' });
454
+ }, []);
455
+
456
+ // Single campaign tracking lane (mirrors trackInApp). `impression` on show,
457
+ // `completion` on submit, `dismiss` on close — the §2.5 analytics events that
458
+ // back the response-rate / completion KPIs (P3-e #2). Distinct from the local
459
+ // throttle store, which only counts impressions for frequency caps.
460
+ const trackCampaign = useCallback(
461
+ (campaign: EngageCampaignConfig, eventType: 'impression' | 'completion' | 'dismiss') => {
462
+ try {
463
+ engage.trackEvent({
464
+ campaignId: campaign.id,
465
+ channel: 'inapp',
466
+ type: eventType,
467
+ deviceId: getDeviceId(),
468
+ });
469
+ } catch (err) {
470
+ logger.debug('[Engage] trackEvent failed:', (err as Error)?.message);
471
+ }
472
+ },
473
+ [engage],
474
+ );
475
+
476
+ const trackSurveyStage = useCallback(
477
+ (campaign: EngageCampaignConfig, stage: 'shown' | 'started'): void => {
478
+ if (campaign.type === 'RATING_PROMPT' || campaign.type === 'RATINGS_PROMPT') return;
479
+ try {
480
+ engage.trackSurveyImpression?.({
481
+ surveyId: campaign.id,
482
+ stage,
483
+ sessionId: currentSessionId(),
484
+ deviceId: getDeviceId(),
485
+ platform: currentPlatform(),
486
+ appVersion: currentAppVersion(),
487
+ screen: activeScreenRef.current,
488
+ });
489
+ } catch (err) {
490
+ logger.debug('[Engage] survey impression failed:', (err as Error)?.message);
491
+ }
492
+ },
493
+ [engage],
494
+ );
495
+
496
+ const isRatingType = (type: EngageCampaignType): boolean =>
497
+ type === 'RATING_PROMPT' || type === 'RATINGS_PROMPT';
498
+
499
+ // Rating-funnel emit lane (ratings-rebuild CONTRACT §1.2). Distinct from
500
+ // trackCampaign (the §2.5 in-app analytics lane) and from submitRating (the D1
501
+ // app-rating lane): these are dimensioned FACTS feeding the Overview funnel and
502
+ // are NEVER counted as responses. `stars` rides only on `rating_selected`.
503
+ const emitRatingFunnel = useCallback(
504
+ (
505
+ campaign: EngageCampaignConfig,
506
+ type: RatingFunnelEventType,
507
+ extra?: { stars?: number },
508
+ ): void => {
509
+ try {
510
+ engage.emitRatingEvent?.({
511
+ type,
512
+ sessionId: currentSessionId(),
513
+ userId: engage.getIdentifiedUserId?.(),
514
+ promptId: campaign.id,
515
+ triggerId: campaign.trigger,
516
+ ...(extra?.stars !== undefined ? { stars: extra.stars } : {}),
517
+ dims: currentRatingDims(),
518
+ });
519
+ } catch (err) {
520
+ logger.debug('[Engage] emitRatingEvent failed:', (err as Error)?.message);
521
+ }
522
+ },
523
+ [engage],
524
+ );
525
+
526
+ const dismissEngagePrompt = useCallback((): void => {
527
+ setActive((current) => {
528
+ if (current) {
529
+ trackCampaign(current, 'dismiss');
530
+ // Rating funnel: a close without a selection is a funnel drop.
531
+ if (isRatingType(current.type)) emitRatingFunnel(current, 'rating_prompt_dismissed');
532
+ }
533
+ return null;
534
+ });
535
+ activeScreenRef.current = undefined;
536
+ surveyStartedRef.current = null;
537
+ resetSubmit();
538
+ }, [trackCampaign, resetSubmit, emitRatingFunnel]);
539
+
540
+ // The actual submit run — used by both the first submit and a retry. Reads
541
+ // `submitCtxRef` + `responseIdRef` so a retry re-sends with the SAME idempotency
542
+ // key. Resolves to `success` ONLY on confirmed persistence; `error` on failure.
543
+ const runSubmit = useCallback(async (): Promise<void> => {
544
+ const ctx = submitCtxRef.current;
545
+ if (!ctx) return;
546
+ const { campaign, result } = ctx;
547
+ const store = storeRef.current;
548
+ const responseId = responseIdRef.current ?? (responseIdRef.current = ratingUuid());
549
+
550
+ setSubmitStatus({ phase: 'submitting', stage: 'saving' });
551
+ try {
552
+ if (isRatingType(campaign.type)) {
553
+ // RATING_PROMPT submits via the EXISTING app-rating lane (D1), NOT
554
+ // submitResponse, with a client clientRatingId for idempotency. Awaited
555
+ // so the loading state reflects the real round-trip.
556
+ const rating = typeof result.score === 'number' ? result.score : 0;
557
+ await Promise.resolve(
558
+ engage.submitRating?.({ rating, source: 'prompt', clientRatingId: responseId }),
559
+ );
560
+ // Funnel: user picked 1–5★ (carries stars). Emitted regardless of route.
561
+ emitRatingFunnel(campaign, 'rating_selected', { stars: rating });
562
+ // Routing decided by the view (`route`), executed against host-supplied
563
+ // callbacks/URL — the deeplink is never hardcoded.
564
+ if (result.route === 'store') {
565
+ // D5: prefer the genuinely-native in-app review sheet. `store_redirect_clicked`
566
+ // fires ONLY when an actual store route resolves (native review ran, or a
567
+ // host-supplied deeplink/callback executed) — never speculatively.
568
+ let redirected = false;
569
+ if (engage.requestStoreReview) {
570
+ redirected = await engage.requestStoreReview();
571
+ }
572
+ const storeUrl = campaign.storeUrl ?? ratingRouting?.storeUrl;
573
+ if (ratingRouting?.onHighRating) {
574
+ ratingRouting.onHighRating({ rating, campaign, storeUrl });
575
+ redirected = true;
576
+ } else if (!redirected && storeUrl) {
577
+ redirected = await Linking.openURL(storeUrl).then(() => true).catch(() => false);
578
+ }
579
+ if (redirected) emitRatingFunnel(campaign, 'store_redirect_clicked');
580
+ } else if (result.route === 'feedback') {
581
+ ratingRouting?.onLowRating?.({ rating, campaign });
582
+ }
583
+ } else {
584
+ // [v2] response context (contract §1): session linkage + originating
585
+ // screen + platform + app version. All optional; omitted when unresolved.
586
+ // We send ONLY the new response fact + the sessionId; replay/errors/network
587
+ // are NOT re-sent — the read side joins them by sessionId.
588
+ const input: EngageResponseInput = Array.isArray(result.answers)
589
+ ? {
590
+ surveyId: campaign.id,
591
+ text: result.reason,
592
+ answers: toWireAnswers(result.answers),
593
+ deviceId: getDeviceId(),
594
+ sessionId: currentSessionId(),
595
+ screen: activeScreenRef.current,
596
+ platform: currentPlatform(),
597
+ appVersion: currentAppVersion(),
598
+ }
599
+ : {
600
+ surveyId: campaign.id,
601
+ score: result.score,
602
+ text: result.reason,
603
+ tags: result.tags,
604
+ deviceId: getDeviceId(),
605
+ sessionId: currentSessionId(),
606
+ screen: activeScreenRef.current,
607
+ platform: currentPlatform(),
608
+ appVersion: currentAppVersion(),
609
+ };
610
+
611
+ const drafts = result.attachments ?? [];
612
+ if (engage.submitResponseConfirmed) {
613
+ // Confirmed lane: awaits real persistence (presign+PUT bytes → response
614
+ // POST), reports stages, idempotent on responseId, throws on failure.
615
+ await engage.submitResponseConfirmed(input, drafts, {
616
+ responseId,
617
+ onStage: (stage) => setSubmitStatus({ phase: 'submitting', stage }),
618
+ });
619
+ } else if (drafts.length > 0 && engage.submitResponseWithAttachments) {
620
+ // Fallback (older facade): fire-and-forget — resolves immediately.
621
+ engage.submitResponseWithAttachments(input, drafts);
622
+ } else {
623
+ engage.submitResponse(input);
624
+ }
625
+ }
626
+
627
+ store?.markCompleted(campaign.id);
628
+ trackCampaign(campaign, 'completion');
629
+ setSubmitStatus({ phase: 'success' });
630
+ // Brief success beat, then close + reset.
631
+ successTimerRef.current = setTimeout(() => {
632
+ setActive(null);
633
+ activeScreenRef.current = undefined;
634
+ resetSubmit();
635
+ }, 1100);
636
+ } catch (err) {
637
+ logger.warn('[Engage] submit failed:', (err as Error)?.message);
638
+ setSubmitStatus({ phase: 'error', message: (err as Error)?.message });
639
+ }
640
+ }, [engage, trackCampaign, ratingRouting, resetSubmit, emitRatingFunnel]);
641
+
642
+ const handleSubmit = useCallback(
643
+ (campaign: EngageCampaignConfig, result: EngagePromptResult): void => {
644
+ // Guard double-submit: ignore re-fires once a submit is in flight or done.
645
+ if (submitCtxRef.current && responseIdRef.current) return;
646
+ submitCtxRef.current = { campaign, result };
647
+ void runSubmit();
648
+ },
649
+ [runSubmit],
650
+ );
651
+
652
+ const closeAfterSubmit = useCallback((): void => {
653
+ setActive(null);
654
+ activeScreenRef.current = undefined;
655
+ resetSubmit();
656
+ }, [resetSubmit]);
657
+
658
+ const showEngagePrompt = useCallback(
659
+ async (options?: ShowEngagePromptOptions): Promise<boolean> => {
660
+ const store = storeRef.current;
661
+ if (!store) return false;
662
+ try {
663
+ const config = await engage.fetchConfig(options?.context);
664
+ if (!config || !Array.isArray(config.campaigns)) return false;
665
+
666
+ const campaign = selectCampaignToRender(config.campaigns, store, {
667
+ // A behavioral-trigger fire (`options.trigger`) is type-agnostic:
668
+ // the trigger itself selects the campaign, so don't layer the
669
+ // NPS-first default on top (it would drop FEEDBACK/CSAT/etc.).
670
+ // Manual fires keep the provider default unless overridden.
671
+ types: options?.types ?? (options?.trigger ? undefined : types),
672
+ screen: options?.screen,
673
+ trigger: options?.trigger,
674
+ seconds: options?.seconds,
675
+ event: options?.event,
676
+ action: options?.action,
677
+ });
678
+ if (!campaign) {
679
+ logger.debug('[Engage] no eligible campaign to render');
680
+ return false;
681
+ }
682
+
683
+ // Record the impression up front so throttle counts it even if the
684
+ // user backgrounds the app before submitting.
685
+ store.recordImpression(campaign.id);
686
+ // Emit the §2.5 impression event (P3-e #2) so the dashboard's
687
+ // response-rate / completion KPIs have a real denominator — the
688
+ // prompt path previously only counted impressions locally.
689
+ trackCampaign(campaign, 'impression');
690
+ // Rating funnel (CONTRACT §1.1): selection passed the throttle/anti-
691
+ // annoyance gate (→ eligible) and we are about to render (→ shown).
692
+ if (isRatingType(campaign.type)) {
693
+ emitRatingFunnel(campaign, 'rating_prompt_eligible');
694
+ emitRatingFunnel(campaign, 'rating_prompt_shown');
695
+ }
696
+ // Stamp the show-time screen alongside the active campaign so
697
+ // handleSubmit can attribute the response to its originating screen.
698
+ activeScreenRef.current = options?.screen;
699
+ surveyStartedRef.current = null;
700
+ trackSurveyStage(campaign, 'shown');
701
+ resetSubmit();
702
+ setActive(campaign);
703
+ return true;
704
+ } catch (err) {
705
+ logger.warn('[Engage] showEngagePrompt failed:', (err as Error)?.message);
706
+ return false;
707
+ }
708
+ },
709
+ [engage, types, trackCampaign, trackSurveyStage, emitRatingFunnel],
710
+ );
711
+
712
+ // ─── In-app message lifecycle (the second Engage family, §2.4/§2.5) ──────
713
+ // Reuses the SAME transport (`trackEvent`), the SAME throttle store, and the
714
+ // SAME provider — NOT a parallel provider. Events: impression on show, click
715
+ // on CTA tap, completion on a finished tour, dismiss on close/skip.
716
+
717
+ const trackInApp = useCallback(
718
+ (
719
+ message: InAppMessageConfig,
720
+ eventType:
721
+ | 'impression'
722
+ | 'completion'
723
+ | 'click'
724
+ | 'dismiss'
725
+ | 'interaction'
726
+ | 'render_degraded'
727
+ | 'render_failed'
728
+ | 'cta_open_failed',
729
+ extraMeta?: Record<string, unknown>,
730
+ ): void => {
731
+ try {
732
+ // A/B attribution (D8/J6): when the active message resolved to an
733
+ // experiment arm, tag every lifecycle event with the chosen variant
734
+ // via the existing optional `meta` field — NO event-schema change
735
+ // (EngageEventUpload already carries `meta`; the backend EngageEvent
736
+ // accepts it). Plain (non-experiment) messages send no variant key.
737
+ const variant = activeInAppVariantRef.current?.variant;
738
+ // [T1] Test-preview tagging: a preview-flagged message stamps
739
+ // `previewId` + `isTest` + `source` so (a) the backend CONSUMES the
740
+ // matching preview row on the impression and (b) production KPIs
741
+ // exclude the traffic. Normal campaign messages omit all of it.
742
+ const isPreview = message.preview === true || message.isTest === true;
743
+ const meta = {
744
+ ...(variant ? { variant } : {}),
745
+ // testRunId correlates a specific "Send Test" run to its render/click/
746
+ // dismiss in the dashboard; rides the existing meta field (no schema churn).
747
+ ...(message.testRunId ? { testRunId: message.testRunId } : {}),
748
+ ...(extraMeta ?? {}),
749
+ };
750
+ engage.trackEvent({
751
+ campaignId: message.id,
752
+ channel: 'inapp',
753
+ type: eventType,
754
+ deviceId: getDeviceId(),
755
+ ...(message.previewId ? { previewId: message.previewId } : {}),
756
+ ...(isPreview ? { isTest: true, source: 'test_preview' } : {}),
757
+ ...(variant ? { variantId: variant } : {}),
758
+ ...(Object.keys(meta).length > 0 ? { meta } : {}),
759
+ });
760
+ } catch (err) {
761
+ logger.debug('[Engage] in-app trackEvent failed:', (err as Error)?.message);
762
+ }
763
+ },
764
+ [engage],
765
+ );
766
+
767
+ // [T1] In-app message actually mounted on screen. The impression event IS the test
768
+ // ACK to the backend (which consumes the preview row → 'rendered'). We ALSO persist the
769
+ // testRunId locally so a cold restart can't re-show it before the ACK is processed
770
+ // server-side — the one-shot guarantee survives a flaky/slow network.
771
+ const handleInAppShow = useCallback(
772
+ (message: InAppMessageConfig): void => {
773
+ // A slot can be replaced or degrade to an overlay while the same message
774
+ // remains active. Treat that as one mount lifecycle, not two impressions.
775
+ if (shownInAppMessageIdRef.current === message.id) return;
776
+ shownInAppMessageIdRef.current = message.id;
777
+ trackInApp(message, 'impression');
778
+ if (message.preview === true || message.isTest === true) {
779
+ const runId = message.testRunId ?? message.previewId ?? message.id;
780
+ seenTestsRef.current?.markSeen(runId);
781
+ // Eager-flush so the backend consumes the one-shot preview row NOW — a fast
782
+ // close→kill→reopen must not re-serve a still-`delivered` test.
783
+ engage.flushEvents?.();
784
+ logger.debug(`[Engage] test ${runId} render displayed — ACK sent (impression), flushed`);
785
+ }
786
+ },
787
+ [trackInApp, engage],
788
+ );
789
+
790
+ const finalizeInAppMessage = useCallback((eventType: 'dismiss' | 'completion'): void => {
791
+ setActiveInApp((current) => {
792
+ if (current) {
793
+ const isTest = current.preview === true || current.isTest === true;
794
+ const runId = current.testRunId ?? current.previewId ?? current.id;
795
+ logger.debug(`[Engage] in-app ${eventType}${isTest ? ` (test ${runId})` : ''}`);
796
+ trackInApp(current, eventType);
797
+ if (isTest) {
798
+ consumedPreviewIds.current.add(current.previewId ?? current.id);
799
+ seenTestsRef.current?.markSeen(runId);
800
+ engage.flushEvents?.();
801
+ logger.debug(`[Engage] test ${runId} ${eventType} persisted + ACK flushed`);
802
+ } else {
803
+ storeRef.current?.markCompleted(current.id);
804
+ engage.flushEvents?.();
805
+ logger.debug(`[Engage] in-app ${current.id} ${eventType} — marked done on device`);
806
+ }
807
+ }
808
+ return null;
809
+ });
810
+ // Clear the resolved A/B arm after the lifecycle event has read it.
811
+ shownInAppMessageIdRef.current = null;
812
+ activeInAppVariantRef.current = null;
813
+ }, [trackInApp, engage]);
814
+
815
+ const dismissInAppMessage = useCallback((): void => {
816
+ finalizeInAppMessage('dismiss');
817
+ }, [finalizeInAppMessage]);
818
+
819
+ const completeInAppMessage = useCallback((): void => {
820
+ finalizeInAppMessage('completion');
821
+ }, [finalizeInAppMessage]);
822
+
823
+ const handleInAppCta = useCallback(
824
+ (message: InAppMessageConfig, cta: NonNullable<InAppRenderSpec['cta']>): void => {
825
+ if (shouldTrackInAppCta(cta)) trackInApp(message, 'click');
826
+ // Deep-link opening is the host's job — surface it, never open it here.
827
+ if (cta.action === 'link') {
828
+ if (!cta.deepLink) {
829
+ // Misconfigured link CTA (no deepLink) — observable, not silent (T1 G17).
830
+ logger.warn('[Engage] link CTA has no deepLink');
831
+ trackInApp(message, 'cta_open_failed', { reason: 'missing_deeplink' });
832
+ } else if (!onInAppDeepLink) {
833
+ // Host wired no deep-link sink — the link can't open. Diagnose it.
834
+ logger.warn('[Engage] link CTA but no onInAppDeepLink handler supplied');
835
+ trackInApp(message, 'cta_open_failed', { reason: 'no_handler' });
836
+ } else {
837
+ try {
838
+ onInAppDeepLink({ message, cta, deepLink: cta.deepLink });
839
+ } catch (err) {
840
+ logger.warn('[Engage] onInAppDeepLink threw:', (err as Error)?.message);
841
+ trackInApp(message, 'cta_open_failed', {
842
+ reason: (err as Error)?.message ?? 'handler_threw',
843
+ });
844
+ }
845
+ }
846
+ }
847
+ // A test preview the user acted on is done — don't re-show it next poll AND
848
+ // persist it durably (a CTA tap is as final as a close), then flush the ACK.
849
+ if (message.preview === true || message.isTest === true) {
850
+ const runId = message.testRunId ?? message.previewId ?? message.id;
851
+ consumedPreviewIds.current.add(message.previewId ?? message.id);
852
+ seenTestsRef.current?.markSeen(runId);
853
+ engage.flushEvents?.();
854
+ logger.debug(`[Engage] test ${runId} CTA — persisted locally + ACK flushed`);
855
+ } else {
856
+ // Production message: a CTA tap is as final as a close — don't re-show it.
857
+ storeRef.current?.markCompleted(message.id);
858
+ engage.flushEvents?.();
859
+ logger.debug(`[Engage] in-app ${message.id} CTA tapped — marked done on device`);
860
+ }
861
+ setActiveInApp(null);
862
+ // Any enabled click event above already read the arm; clear it now.
863
+ shownInAppMessageIdRef.current = null;
864
+ activeInAppVariantRef.current = null;
865
+ },
866
+ [trackInApp, onInAppDeepLink, engage],
867
+ );
868
+
869
+ // [T1] Pick the ONE test preview to render from a fetched config: drop any already
870
+ // displayed (persistent seen store) or closed-this-session, then take the LATEST by
871
+ // createdAt. One-shot + latest-only is what stops the "tests stack up 1,2,3…" bug.
872
+ const pickLatestPreview = useCallback(
873
+ (messages: InAppMessageConfig[]): InAppMessageConfig | null => {
874
+ const latest = selectLatestUnseenTest(messages, {
875
+ seen: (runId) => seenTestsRef.current?.has(runId) ?? false,
876
+ consumed: (key) => consumedPreviewIds.current.has(key),
877
+ });
878
+ if (latest) logger.debug(`[Engage] selected latest test ${testRunIdOf(latest)}`);
879
+ return latest;
880
+ },
881
+ [],
882
+ );
883
+
884
+ // [T1] Render a test preview IMMEDIATELY — bypassing trigger/throttle/schedule/
885
+ // sample/variant. No throttle write (a preview must stay re-showable until it is
886
+ // actually rendered + its impression consumes it server-side). Idempotent: if this
887
+ // exact preview is already on screen, don't re-mount (avoids a duplicate impression).
888
+ const showPreview = useCallback(
889
+ (preview: InAppMessageConfig): boolean => {
890
+ // PRECEDENCE: a campaign prompt owns the screen — defer (the backend re-serves
891
+ // the preview on every poll until TTL, so the next foreground retries).
892
+ if (active !== null) {
893
+ logger.debug('[Engage] campaign prompt active — preview deferred');
894
+ return false;
895
+ }
896
+ if (activeInApp?.id === preview.id) return true;
897
+ const runId = preview.testRunId ?? preview.previewId ?? preview.id;
898
+ // Already closed this preview this session — don't re-show on the next poll.
899
+ if (consumedPreviewIds.current.has(preview.previewId ?? preview.id)) {
900
+ return false;
901
+ }
902
+ // [T1] One-shot: already DISPLAYED on this device (persisted across restarts) —
903
+ // never re-show, even if the backend briefly re-serves a not-yet-ACKed row.
904
+ if (seenTestsRef.current?.has(runId)) {
905
+ logger.debug(`[Engage] test ${runId} already displayed on device — skip`);
906
+ return false;
907
+ }
908
+ activeInAppVariantRef.current = null;
909
+ setActiveInApp(preview);
910
+ logger.debug(`[Engage] test ${runId} render started`);
911
+ return true;
912
+ },
913
+ [active, activeInApp],
914
+ );
915
+
916
+ const showInAppMessage = useCallback(
917
+ async (options?: ShowInAppMessageOptions): Promise<boolean> => {
918
+ const store = storeRef.current;
919
+ if (!store) return false;
920
+ // PRECEDENCE: a campaign prompt on screen wins — never stack an in-app
921
+ // message over an open survey/NPS/rating prompt.
922
+ if (active !== null) {
923
+ logger.debug('[Engage] campaign prompt active — in-app message deferred');
924
+ return false;
925
+ }
926
+ try {
927
+ const config = await engage.fetchConfig(buildConfigContext(engage, options?.context));
928
+ if (!config || !Array.isArray(config.inAppMessages)) return false;
929
+
930
+ // [T1] A queued test preview wins immediately, bypassing throttle/variant.
931
+ // Pick the LATEST unseen one (one-shot dedupe) — never stack old tests.
932
+ const preview = pickLatestPreview(config.inAppMessages);
933
+ if (preview) return showPreview(preview);
934
+
935
+ // Normal selection runs over NON-preview messages only — a preview must
936
+ // never enter the throttle store (it would falsely cap a real campaign id).
937
+ const normal = config.inAppMessages.filter(
938
+ (m) => !(m.preview === true || m.isTest === true),
939
+ );
940
+ const message = selectInAppToRender(normal, store, {
941
+ screen: options?.screen,
942
+ trigger: options?.trigger,
943
+ seconds: options?.seconds,
944
+ event: options?.event,
945
+ action: options?.action,
946
+ });
947
+ if (!message) {
948
+ logger.debug('[Engage] no eligible in-app message to render');
949
+ return false;
950
+ }
951
+
952
+ // A/B variant selection (D8/J6): deterministically bucket this
953
+ // device into arm A (base spec) or B (experiment.variantB) BEFORE
954
+ // showing, so the impression event (and click/dismiss) attribute to
955
+ // the arm the user actually saw. Only retained for attribution when
956
+ // the message actually carries an enabled experiment; otherwise the
957
+ // resolved spec is just the base spec and no variant key is emitted.
958
+ const resolved = selectInAppVariant(message, getDeviceId());
959
+ activeInAppVariantRef.current = message.experiment?.enabled
960
+ ? resolved
961
+ : null;
962
+ // Record up front so the throttle counts it (impression also emitted
963
+ // by the view's onShow → trackEvent for the analytics lane). Pass the
964
+ // content revision so an edited campaign starts a fresh cap generation.
965
+ store.recordImpression(message.id, Date.now(), message.revision);
966
+ setActiveInApp(message);
967
+ return true;
968
+ } catch (err) {
969
+ logger.warn('[Engage] showInAppMessage failed:', (err as Error)?.message);
970
+ return false;
971
+ }
972
+ },
973
+ [engage, active, showPreview, pickLatestPreview],
974
+ );
975
+
976
+ // ─── Cold-start + foreground preview check (T1) ──────────────────────────
977
+ // "Send Test → reopen the app → see it immediately, EVERY time": the SDK fetches
978
+ // config (deviceId in context, HTTP cache-bypassed) on mount AND on every
979
+ // AppState→active, and renders any queued preview at once — no trigger, no throttle,
980
+ // no schedule. The backend keeps serving the preview on every poll until its TTL, so
981
+ // a tester sees it on each reopen (rendering records lifecycle but does not consume).
982
+ const checkForPreview = useCallback(async (): Promise<void> => {
983
+ if (active !== null) return;
984
+ try {
985
+ const config = await engage.fetchConfig(buildConfigContext(engage));
986
+ // One-shot + latest-only: render the newest test not already displayed.
987
+ const preview = pickLatestPreview(config?.inAppMessages ?? []);
988
+ if (preview) showPreview(preview);
989
+ } catch (err) {
990
+ logger.warn('[Engage] preview check failed:', (err as Error)?.message);
991
+ }
992
+ }, [engage, active, showPreview, pickLatestPreview]);
993
+
994
+ useEffect(() => {
995
+ // Drop stale seen-test entries (past TTL) so the persistent set stays bounded.
996
+ seenTestsRef.current?.prune();
997
+ void checkForPreview();
998
+ const onLifecycle = (state: string): void => {
999
+ if (state === 'active') void checkForPreview();
1000
+ };
1001
+ appLifecycle.addListener(onLifecycle);
1002
+ return () => appLifecycle.removeListener(onLifecycle);
1003
+ }, [checkForPreview]);
1004
+
1005
+ // DEV/TEST warm-foreground poll (T1): covers "Send Test while the app is already
1006
+ // open" — no background→foreground edge fires, so without this you'd have to switch
1007
+ // apps to see it. Only runs when the host opts in via `previewPollMs` (unset in prod).
1008
+ useEffect(() => {
1009
+ if (!previewPollMs || previewPollMs <= 0) return;
1010
+ logger.debug(`[Engage] test-preview warm poll every ${previewPollMs}ms (dev)`);
1011
+ const interval = setInterval(() => {
1012
+ void checkForPreview();
1013
+ }, previewPollMs);
1014
+ return () => clearInterval(interval);
1015
+ }, [previewPollMs, checkForPreview]);
1016
+
1017
+ // ─── Always-on behavioral triggers (P3-e #3 / Slice E) ───────────────────
1018
+ // The trigger engine wires every behavioral trigger (session_start, app_open,
1019
+ // screen_view/exit, time_in_app, n_sessions, after_purchase, before_logout,
1020
+ // custom_event, failed_action, after_crash/js_error, network_error, slow_screen,
1021
+ // and the native gesture triggers) to the SDK signals the app already produces.
1022
+ // A fire first tries the survey/rating campaign path (showEngagePrompt); if no
1023
+ // campaign matches, the SAME trigger drives an in-app message (showInAppMessage).
1024
+ // Both families share the throttle store, so a behavioral fire never double-shows.
1025
+ // The engine buffers events fired before the first config arrives and replays
1026
+ // them once it does (late binding), honoring each trigger's remaining delay.
1027
+ useEffect(() => {
1028
+ return installEngageTriggerEngine({
1029
+ fire: (options) => {
1030
+ void (async () => {
1031
+ const shown = await showEngagePrompt(options);
1032
+ if (!shown && options.trigger) {
1033
+ await showInAppMessage({
1034
+ trigger: options.trigger,
1035
+ screen: options.screen,
1036
+ event: options.event,
1037
+ action: options.action,
1038
+ seconds: options.seconds,
1039
+ });
1040
+ }
1041
+ })();
1042
+ },
1043
+ fetchConfig: () => engage.fetchConfig(buildConfigContext(engage)),
1044
+ });
1045
+ }, [showEngagePrompt, showInAppMessage, engage]);
1046
+
1047
+ const controller = useMemo<EngagePromptController>(
1048
+ () => ({
1049
+ showEngagePrompt,
1050
+ dismissEngagePrompt,
1051
+ showInAppMessage,
1052
+ dismissInAppMessage,
1053
+ }),
1054
+ [showEngagePrompt, dismissEngagePrompt, showInAppMessage, dismissInAppMessage],
1055
+ );
1056
+
1057
+ const activeInAppSpec = activeInAppVariantRef.current?.spec ?? activeInApp?.spec;
1058
+ const activeInAppPresentation = activeInApp && activeInAppSpec
1059
+ ? resolveInAppPresentation({
1060
+ layout: activeInApp.layout,
1061
+ variantKey: activeInApp.variantKey,
1062
+ spec: activeInAppSpec,
1063
+ })
1064
+ : null;
1065
+ // Route by the canonical mount, not a variant allow-list. This covers every
1066
+ // current/future inline variant, including smart_inbox_message.
1067
+ const routesToInlineSlot = activeInAppPresentation?.mountModel === 'inline';
1068
+ const inlinePlacement = resolveEngageInlinePlacement(activeInAppSpec);
1069
+
1070
+ const handleActiveInAppShow = useCallback((): void => {
1071
+ if (!activeInApp) return;
1072
+ handleInAppShow(activeInApp);
1073
+ const tourId = activeInApp.spec.ext?.coachTourId;
1074
+ const first = Array.isArray(activeInApp.spec.ext?.steps) ? activeInApp.spec.ext?.steps[0] as Record<string, unknown> | undefined : undefined;
1075
+ if (typeof tourId === 'string') {
1076
+ engage.trackCoachmarkEvent?.('$coachmark_tour_started', { tourId });
1077
+ engage.trackCoachmarkEvent?.('$coachmark_step_entered', {
1078
+ tourId,
1079
+ stepId: String(first?.id ?? first?.anchorKey ?? '1'),
1080
+ });
1081
+ }
1082
+ }, [activeInApp, handleInAppShow, engage]);
1083
+ const handleActiveInAppCta = useCallback((cta: NonNullable<InAppRenderSpec['cta']>): void => {
1084
+ if (activeInApp) handleInAppCta(activeInApp, cta);
1085
+ }, [activeInApp, handleInAppCta]);
1086
+ const handleActiveInAppInteraction = useCallback((interaction: InAppMechanicInteraction): void => {
1087
+ if (!activeInApp) return;
1088
+ trackInApp(activeInApp, 'interaction', { interaction });
1089
+ const tourId = activeInApp.spec.ext?.coachTourId;
1090
+ if (typeof tourId !== 'string' || interaction.mechanic !== 'coachmark_spotlight') return;
1091
+ const meta = interaction.meta ?? {};
1092
+ const stepId = String(meta.anchorKey ?? meta.step ?? meta.toStep ?? 'unknown');
1093
+ if (interaction.result === 'step_viewed' && interaction.phase !== 'started') {
1094
+ engage.trackCoachmarkEvent?.('$coachmark_step_entered', { tourId, stepId });
1095
+ } else if (interaction.phase === 'completed') {
1096
+ engage.trackCoachmarkEvent?.('$coachmark_tour_completed', { tourId, stepId });
1097
+ } else if (interaction.result === 'skipped') {
1098
+ engage.trackCoachmarkEvent?.('$coachmark_tour_abandoned', { tourId, stepId });
1099
+ }
1100
+ }, [activeInApp, trackInApp, engage]);
1101
+ const handleActiveInAppRenderError = useCallback((reason: string): void => {
1102
+ if (activeInApp) {
1103
+ trackInApp(activeInApp, 'render_failed', { reason });
1104
+ const tourId = activeInApp.spec.ext?.coachTourId;
1105
+ if (typeof tourId === 'string') {
1106
+ const anchorKey = reason.startsWith('anchor_not_found:') ? reason.slice('anchor_not_found:'.length) : 'unknown';
1107
+ engage.trackCoachmarkEvent?.('$coachmark_anchor_failed', {
1108
+ tourId,
1109
+ stepId: anchorKey,
1110
+ reason: reason.startsWith('anchor_not_found:') ? 'anchor_not_found' : reason,
1111
+ });
1112
+ }
1113
+ }
1114
+ shownInAppMessageIdRef.current = null;
1115
+ activeInAppVariantRef.current = null;
1116
+ setActiveInApp(null);
1117
+ }, [activeInApp, trackInApp, engage]);
1118
+
1119
+ useEffect(() => {
1120
+ if (!routesToInlineSlot || !inlinePlacement.placementKey) return;
1121
+ return inlinePlacementRegistry.subscribe(inlinePlacement.placementKey, () => {
1122
+ setInlinePlacementRevision((revision) => revision + 1);
1123
+ });
1124
+ }, [inlinePlacement.placementKey, inlinePlacementRegistry, routesToInlineSlot]);
1125
+
1126
+ useEffect(() => {
1127
+ if (!activeInApp || active !== null || !routesToInlineSlot) {
1128
+ setInlineFallbackMessageId(null);
1129
+ return;
1130
+ }
1131
+
1132
+ const messageId = activeInApp.id;
1133
+ // Once this message has visibly degraded, keep it on that mount. Moving it
1134
+ // into a late slot would create a second renderer and a misleading lifecycle.
1135
+ if (inlineFallbackMessageId === messageId) return;
1136
+ const reason = inlinePlacement.placementKey
1137
+ ? `inline_placement_not_found:${inlinePlacement.placementKey}`
1138
+ : 'missing_inline_placement_key';
1139
+ const delivery: EngageInlineDelivery = {
1140
+ message: activeInApp,
1141
+ spec: activeInAppSpec,
1142
+ onShow: handleActiveInAppShow,
1143
+ onCta: handleActiveInAppCta,
1144
+ onDismiss: dismissInAppMessage,
1145
+ onComplete: completeInAppMessage,
1146
+ onInteraction: handleActiveInAppInteraction,
1147
+ onInAppGameRequest,
1148
+ onRenderError: handleActiveInAppRenderError,
1149
+ };
1150
+ const delivered = inlinePlacementRegistry.deliver(
1151
+ inlinePlacement.placementKey,
1152
+ delivery,
1153
+ );
1154
+
1155
+ if (delivered) {
1156
+ setInlineFallbackMessageId(null);
1157
+ } else {
1158
+ inlinePlacementRegistry.clear(inlinePlacement.placementKey, messageId);
1159
+ if (inlinePlacement.fallback === 'skip') {
1160
+ setInlineFallbackMessageId(null);
1161
+ handleActiveInAppRenderError(reason);
1162
+ } else {
1163
+ // Preserve the legacy visible behavior, but make the degradation observable.
1164
+ trackInApp(activeInApp, 'render_degraded', {
1165
+ reason,
1166
+ placementKey: inlinePlacement.placementKey,
1167
+ fallback: 'overlay',
1168
+ });
1169
+ setInlineFallbackMessageId(messageId);
1170
+ }
1171
+ }
1172
+
1173
+ return () => inlinePlacementRegistry.clear(inlinePlacement.placementKey, messageId);
1174
+ }, [
1175
+ active,
1176
+ activeInApp,
1177
+ activeInAppSpec,
1178
+ dismissInAppMessage,
1179
+ completeInAppMessage,
1180
+ handleActiveInAppCta,
1181
+ handleActiveInAppInteraction,
1182
+ handleActiveInAppRenderError,
1183
+ handleActiveInAppShow,
1184
+ inlinePlacement.fallback,
1185
+ inlinePlacement.placementKey,
1186
+ inlinePlacementRegistry,
1187
+ inlineFallbackMessageId,
1188
+ inlinePlacementRevision,
1189
+ onInAppGameRequest,
1190
+ routesToInlineSlot,
1191
+ trackInApp,
1192
+ ]);
1193
+
1194
+ const rootInAppVisible = activeInApp !== null &&
1195
+ active === null &&
1196
+ (!routesToInlineSlot || inlineFallbackMessageId === activeInApp.id);
1197
+
1198
+ return (
1199
+ <EngageAnchorProvider>
1200
+ <EngageInlinePlacementProvider registry={inlinePlacementRegistry}>
1201
+ <EngagePromptContext.Provider value={controller}>
1202
+ {children}
1203
+ <EngagePromptView
1204
+ campaign={active}
1205
+ visible={active !== null}
1206
+ rating={ratingRouting}
1207
+ submitStatus={submitStatus}
1208
+ onRetrySubmit={() => void runSubmit()}
1209
+ onCloseSubmit={closeAfterSubmit}
1210
+ onSubmit={(result) => {
1211
+ if (active) handleSubmit(active, result);
1212
+ }}
1213
+ onStart={() => {
1214
+ if (active && surveyStartedRef.current !== active.id) {
1215
+ surveyStartedRef.current = active.id;
1216
+ trackSurveyStage(active, 'started');
1217
+ }
1218
+ }}
1219
+ onDismiss={dismissEngagePrompt}
1220
+ />
1221
+ {/* In-app message overlay. PRECEDENCE: only visible when no campaign
1222
+ prompt is on screen, so the two families never fight for the view. */}
1223
+ <EngageInAppView
1224
+ message={activeInApp}
1225
+ visible={rootInAppVisible}
1226
+ mountModelOverride={routesToInlineSlot && inlineFallbackMessageId === activeInApp?.id
1227
+ ? 'overlay'
1228
+ : undefined}
1229
+ // Render the resolved A/B arm's content (D8/J6) when an experiment is
1230
+ // active; undefined ⇒ the view falls back to the message's base spec.
1231
+ spec={activeInAppVariantRef.current?.spec}
1232
+ onShow={handleActiveInAppShow}
1233
+ onCta={handleActiveInAppCta}
1234
+ onDismiss={dismissInAppMessage}
1235
+ onComplete={completeInAppMessage}
1236
+ onInteraction={handleActiveInAppInteraction}
1237
+ onInAppGameRequest={onInAppGameRequest}
1238
+ onRenderError={handleActiveInAppRenderError}
1239
+ />
1240
+ </EngagePromptContext.Provider>
1241
+ </EngageInlinePlacementProvider>
1242
+ </EngageAnchorProvider>
1243
+ );
1244
+ }
1245
+
1246
+ /**
1247
+ * Hook a host app uses to trigger/dismiss the prompt:
1248
+ * const { showEngagePrompt } = useEngagePrompt();
1249
+ * showEngagePrompt({ types: ['NPS'] });
1250
+ */
1251
+ export function useEngagePrompt(): EngagePromptController {
1252
+ const ctx = useContext(EngagePromptContext);
1253
+ if (!ctx) {
1254
+ // Fail-soft: a host that calls the hook outside the provider gets no-ops
1255
+ // instead of a crash (matches the SDK's no-throw public-API style).
1256
+ return {
1257
+ showEngagePrompt: async () => {
1258
+ logger.warn('[Engage] useEngagePrompt() called outside <EngagePromptProvider>');
1259
+ return false;
1260
+ },
1261
+ dismissEngagePrompt: () => {},
1262
+ showInAppMessage: async () => {
1263
+ logger.warn('[Engage] useEngagePrompt() called outside <EngagePromptProvider>');
1264
+ return false;
1265
+ },
1266
+ dismissInAppMessage: () => {},
1267
+ };
1268
+ }
1269
+ return ctx;
1270
+ }