@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,1233 +1,1233 @@
1
- /**
2
- * ScaleBun SDK — Backend Session Adapter
3
- *
4
- * Implements the SessionTransport interface (System A) and bridges
5
- * session/frame/event data to the backend API via HTTP.
6
- *
7
- * This is the ADAPTER that connects the existing SessionManager
8
- * (which only has DesktopSessionTransport) to the backend.
9
- *
10
- * Design:
11
- * - Uses the same endpoint contract as BackendReplayTransport
12
- * (POST /v1/replay/sessions, /frames, /events, /finalize)
13
- * - Batches frames and events with auto-flush
14
- * - Never throws — all errors are caught and logged
15
- * - Behind config flag: only constructed when backendUpload is enabled
16
- *
17
- * This does NOT duplicate the existing BackendReplayTransport.
18
- * It exists because SessionManager uses a different interface
19
- * (SessionTransport from sessionTypes.ts) than ReplayTransport
20
- * (from features/replay/transport/ReplayTransport.ts).
21
- * The payload shapes differ, so this adapter maps between them.
22
- *
23
- * MVP/dev-only: base64 frames are sent inline in JSON body.
24
- */
25
-
26
- import { logger } from '../../core/logger/internalLogger';
27
- import { base64ToBytes } from '../../core/encoding/base64';
28
- import { ENDPOINTS } from '../../transport/http/endpoints';
29
- import { SDK_VERSION } from '../../core/constants/version';
30
- import { bridgeAdapter } from '../replay/bridge/adapters/bridgeAdapter';
31
- import { getReplaySdkNative } from '../replay/bridge/nativeModule';
32
- import type { ReplaySdkNativeModule } from '../replay/bridge/nativeModule';
33
- import type { StorageBackend } from '../../storage/StorageBackend';
34
- import type {
35
- SessionTransport,
36
- Session,
37
- SessionMetadata,
38
- JourneyEvent,
39
- ReplayFrame,
40
- } from './sessionTypes';
41
-
42
- // ─── Config ─────────────────────────────────────────────────────────────────
43
-
44
- export interface BackendSessionConfig {
45
- /** Backend API base URL (e.g. http://localhost:3001/api) */
46
- endpoint: string;
47
- /** Batch size for frames before auto-flush. Default: 5 */
48
- batchSize?: number;
49
- /** Auto-flush interval in ms. Default: 3000 */
50
- flushIntervalMs?: number;
51
- /** Request timeout in ms. Default: 15000 */
52
- timeoutMs?: number;
53
- /** SaaS multi-tenant client key — enables ingestion endpoints and x-scalebun-client-key header */
54
- clientKey?: string;
55
- /**
56
- * Upload frame bytes directly to object storage via presigned PUT instead of
57
- * inline base64 in the JSON body. Default false → legacy inline path. Flip on
58
- * after the backend presign endpoint is deployed. Falls back to inline
59
- * automatically if the backend reports storage is not configured.
60
- */
61
- useObjectStorage?: boolean;
62
- /**
63
- * Route telemetry lanes (events/network/errors/performance/logs) through the
64
- * durable NATIVE file outbox instead of JS-side HTTP. Only takes effect when BOTH
65
- * this and `nativeOutboxUploadEnabled` are true AND the native module exposes the
66
- * outbox methods — otherwise the existing JS upload path is used unchanged. When
67
- * active, the native uploader owns delivery (no duplicate JS POST). Default false.
68
- */
69
- enableNativeFileOutbox?: boolean;
70
- /** Native outbox actually uploads (vs. capture/store-only). Gates telemetry routing. */
71
- nativeOutboxUploadEnabled?: boolean;
72
- /**
73
- * Additive native-outbox tuning flags (retry interval, attempt caps, Retry-After,
74
- * byte/age GC bounds, etc.) forwarded verbatim to the native `initOutbox` dict.
75
- * Native parses both `nativeOutbox*` and bare `outbox*` keys and applies its own
76
- * defaults for anything omitted — so an empty object changes nothing.
77
- */
78
- nativeOutboxTuning?: Record<string, unknown>;
79
- /** Idle-gap threshold (ms) the SDK recorded with; persisted on the session row. */
80
- idleThresholdMs?: number;
81
- /**
82
- * Durable key-value store used to persist the unflushed frame buffer across a
83
- * process kill. On background the in-flight frames are snapshotted here; on the
84
- * next launch they are re-uploaded and linked to the PRIOR session. Omitted →
85
- * frame-kill recovery is disabled (in-memory only, prior behavior).
86
- */
87
- storage?: StorageBackend;
88
- }
89
-
90
- /**
91
- * One platform-agnostic log line for the logs lane. The queue forwards whatever it is
92
- * given — `source`/`platform` are neutral string hints set by the PRODUCER (console
93
- * tags 'console'/'js'; a future native producer tags its own values onto this SAME
94
- * shape). `level` is free-text. Nothing here is JS-specific.
95
- */
96
- export interface LogQueueItem {
97
- level: string;
98
- message: string;
99
- source: string;
100
- platform: string;
101
- timestamp: string;
102
- metadata?: Record<string, unknown>;
103
- }
104
-
105
- // ─── Adapter ────────────────────────────────────────────────────────────────
106
-
107
- export class BackendSessionAdapter implements SessionTransport {
108
- private config: Required<Omit<BackendSessionConfig, 'clientKey' | 'storage'>> & { clientKey?: string; storage?: StorageBackend };
109
- /** Durable store for cross-kill frame recovery (null → recovery disabled). */
110
- private readonly _frameStore: StorageBackend | null;
111
- /** Storage key for the snapshotted unflushed frame buffer (see persistPendingFrames). */
112
- private static readonly PENDING_FRAMES_KEY = 'scalebun_replay_pending_frames';
113
- /** Cap on frames persisted per snapshot — bounds KV footprint (keeps the most recent). */
114
- private static readonly MAX_PERSIST_FRAMES = 10;
115
- // Per-session toggle: cleared to false if the backend reports storage disabled.
116
- private objectStorageActive: boolean;
117
- // True when telemetry should divert to the durable native outbox (both flags on).
118
- // Native module availability is re-checked per call so a missing/old binary falls
119
- // back to the JS path transparently.
120
- private readonly nativeOutboxEnabled: boolean;
121
- // Cached one-shot native-outbox bootstrap promise (see _ensureNativeOutbox).
122
- private _nativeOutboxReady: Promise<boolean> | null = null;
123
- private currentSessionId: string | null = null;
124
- // §11 session_start ordering: a recording sessionId is added here ONLY after its
125
- // INGESTION_START row is confirmed created on the backend (either via sendSessionStart's
126
- // own POST, or via startAnalyticsSession when recording adopts the analytics id).
127
- // Child telemetry lanes (frames/events/network/errors/perf/logs) refuse to flush until
128
- // the row exists — otherwise the backend 404s the child write. Data stays buffered and
129
- // the flush timer retries, so nothing is lost to a start/child race. The durable native
130
- // outbox path has its own ordering; this guards only the JS in-memory fallback.
131
- private readonly _startedSessionIds = new Set<string>();
132
- private pendingFrames: Array<{ frame: ReplayFrame; imageData: string }> = [];
133
- private pendingEvents: JourneyEvent[] = [];
134
- private pendingNetworkRequests: Array<Record<string, unknown>> = [];
135
- private pendingErrors: Array<Record<string, unknown>> = [];
136
- private pendingPerformanceMetrics: Array<Record<string, unknown>> = [];
137
- // Platform-agnostic logs lane. Neutral by construction — holds whatever LogQueueItems
138
- // it's handed (console today; native later) and forwards them untouched.
139
- private pendingLogs: LogQueueItem[] = [];
140
- private flushTimer: ReturnType<typeof setInterval> | null = null;
141
- private destroyed = false;
142
-
143
- // ── Analytics lane (always-on, foreground-scoped; isolated from recording) ──
144
- // Fully separate from currentSessionId/pendingEvents/_flushEvents, which serve
145
- // recording. This lane carries user track() events and never touches recording
146
- // state. One queue doubles as the pre-ready buffer (bounded, drop-oldest) and
147
- // the outgoing queue; sessionId is stamped at flush so endpoint id == body id.
148
- private static readonly ANALYTICS_BUFFER_CAP = 100;
149
- /** Logs lane: queue length that triggers an eager flush (mirrors the network lane). */
150
- private static readonly LOGS_BATCH_SIZE = 20;
151
- /** Logs lane: max rows posted per flush (server caps at 200/batch). */
152
- private static readonly LOGS_FLUSH_MAX = 50;
153
- private _analyticsSessionId: string | null = null;
154
- private pendingAnalyticsEvents: JourneyEvent[] = [];
155
- private analyticsFlushTimer: ReturnType<typeof setInterval> | null = null;
156
- // iOS finalize reconciliation: the id of a backgrounded analytics session whose
157
- // INGESTION_FINALIZE has NOT been confirmed delivered. Set synchronously in
158
- // finalizeAnalyticsSession before any await (so it survives an iOS suspension of
159
- // the awaited fetch), cleared only on a confirmed finalize ACK. On the next
160
- // foreground the listener calls reconcilePendingFinalize() to close it for real.
161
- // In-memory is sufficient: the JS context survives background→foreground; only a
162
- // true process kill drops it (covered by the server-side idle-close backstop).
163
- private _pendingFinalizeId: string | null = null;
164
-
165
- constructor(config: BackendSessionConfig) {
166
- this.config = {
167
- batchSize: 5,
168
- flushIntervalMs: 3000,
169
- timeoutMs: 15_000,
170
- useObjectStorage: false,
171
- enableNativeFileOutbox: false,
172
- nativeOutboxUploadEnabled: false,
173
- nativeOutboxTuning: {},
174
- idleThresholdMs: 60_000,
175
- ...config,
176
- clientKey: config.clientKey,
177
- };
178
- this._frameStore = config.storage ?? null;
179
- this.objectStorageActive = this.config.useObjectStorage;
180
- this.nativeOutboxEnabled =
181
- this.config.enableNativeFileOutbox && this.config.nativeOutboxUploadEnabled;
182
- logger.info(`[ScaleBun Replay] backendUpload enabled`);
183
- logger.info(`[ScaleBun Replay] backendBaseUrl: ${this.config.endpoint}`);
184
- logger.info(`[ScaleBun Replay] transport fan-out active: desktop yes, backend yes`);
185
- }
186
-
187
- // ─── SessionTransport Interface ─────────────────────────────────────
188
-
189
- /**
190
- * §11 gate: true only when the current recording session's INGESTION_START row is
191
- * confirmed on the backend. Child telemetry lanes consult this before flushing so they
192
- * never race ahead of session creation (which would 404). Null id → not ready.
193
- */
194
- private _sessionRowReady(): boolean {
195
- return !!this.currentSessionId && this._startedSessionIds.has(this.currentSessionId);
196
- }
197
-
198
- sendSessionStart(session: Session): void {
199
- this.currentSessionId = session.sessionId;
200
- this._startFlushTimer();
201
-
202
- logger.info(`[ScaleBun Replay] session start requested`);
203
- logger.info(`[ScaleBun Replay] sessionId: ${session.sessionId}`);
204
- logger.info(`[ScaleBun Replay] deviceId: ${session.deviceId}`);
205
- logger.info(`[ScaleBun Replay] recordingSessionId: ${session.sessionId}`);
206
-
207
- // One-row merge: when recording adopted the always-on analytics id
208
- // (SessionManager.startSession), the INGESTION_START row already exists.
209
- // Do NOT post a second one — just keep the flush timer running so frames/
210
- // journey/network/errors/perf flush to INGESTION_*(analyticsId). Legacy
211
- // mode (no clientKey, distinct minted id) still posts /replay/sessions.
212
- if (this.config.clientKey && session.sessionId === this._analyticsSessionId) {
213
- logger.info(`[ScaleBun Replay] recording attached to analytics session ${session.sessionId} (no new row)`);
214
- return;
215
- }
216
-
217
- logger.info(`[ScaleBun Replay] backend session upload started`);
218
-
219
- const startEndpoint = this.config.clientKey ? ENDPOINTS.INGESTION_START : '/replay/sessions';
220
-
221
- // Fetch native device info to enrich the session payload.
222
- // Falls back to metadata-only if bridge unavailable (old native binary).
223
- bridgeAdapter.getDeviceInfo()
224
- .then(nativeInfo => {
225
- const m = session.metadata;
226
- const payload = {
227
- sessionId: session.sessionId,
228
- deviceId: session.deviceId,
229
- startedAt: session.startedAt,
230
- // Link the recording row to the always-on analytics row so the
231
- // dashboard can join them. track() events land on the analytics
232
- // id; frames/journey land on this recording id. Without this
233
- // link the two appear as separate sessions (one looks "empty").
234
- // BACKEND DEPENDENCY: the dashboard must read/join on this field
235
- // (or treat the analytics row as canonical) to fully merge them.
236
- analyticsSessionId: this._analyticsSessionId,
237
- // Carry the idle threshold on the recording lane too: it may
238
- // create the row before the analytics lane does. Backend
239
- // upsert leaves it untouched if already set.
240
- idleThresholdMs: this.config.idleThresholdMs,
241
- device: {
242
- platform: nativeInfo?.platform ?? m?.platform,
243
- osVersion: nativeInfo?.osVersion ?? m?.osVersion,
244
- deviceModel: nativeInfo?.deviceModel ?? m?.deviceModel,
245
- screenWidth: m?.screenWidth,
246
- screenHeight: m?.screenHeight,
247
- appName: nativeInfo?.appName ?? m?.appName,
248
- appVersion: nativeInfo?.appVersion ?? m?.appVersion,
249
- bundleId: nativeInfo?.bundleId ?? m?.bundleId,
250
- sdkVersion: SDK_VERSION,
251
- releaseStage: m?.buildType,
252
- // Backend ingestion source not in this repo; field name
253
- // unconfirmed. Send both so whichever it reads is populated.
254
- environment: m?.buildType,
255
- },
256
- };
257
- logger.debug(`[BackendSessionAdapter] POST session start: ${session.sessionId}`);
258
- return this._post(startEndpoint, payload);
259
- })
260
- .then(() => {
261
- // §11: row now exists — release the child-lane flush gate for this id.
262
- this._startedSessionIds.add(session.sessionId);
263
- logger.info(`[ScaleBun Replay] backend session upload success`);
264
- })
265
- .catch(() => logger.info(`[ScaleBun Replay] backend session upload failure`));
266
- }
267
-
268
- sendSessionEnd(session: Session): void {
269
- logger.info(`[ScaleBun Replay] finalize started`);
270
- // Flush all pending data first, then finalize
271
- Promise.all([
272
- this._flushFrames(),
273
- this._flushEvents(),
274
- this._flushNetwork(),
275
- this._flushErrors(),
276
- this._flushPerformance(),
277
- ]).then(() => {
278
- // One-row merge: if this recording adopted the always-on analytics id,
279
- // the analytics lane owns the session's lifecycle and finalizes it on
280
- // background (finalizeAnalyticsSession). Finalizing here would close the
281
- // shared row mid-foreground and orphan later track() events — so flush
282
- // (above) but skip finalize. Legacy/distinct-id sessions finalize normally.
283
- if (this.config.clientKey && session.sessionId === this._analyticsSessionId) {
284
- logger.info(`[ScaleBun Replay] recording ended; analytics session ${session.sessionId} stays open`);
285
- return;
286
- }
287
- const finalizeEndpoint = this.config.clientKey
288
- ? ENDPOINTS.INGESTION_FINALIZE(session.sessionId)
289
- : `/replay/sessions/${session.sessionId}/finalize`;
290
- return this._post(
291
- finalizeEndpoint,
292
- {
293
- endedAt: session.endedAt ?? Date.now(),
294
- durationMs: session.endedAt
295
- ? session.endedAt - session.startedAt
296
- : Date.now() - session.startedAt,
297
- totalFrames: session.artifactIndex?.frameRefs?.length ?? 0,
298
- totalEvents: session.artifactIndex?.eventRefs?.length ?? 0,
299
- finalState: session.status === 'timeout' ? 'timeout' : 'completed',
300
- },
301
- );
302
- }).then(() => {
303
- logger.info(`[ScaleBun Replay] finalize success`);
304
- }).catch(() => {
305
- logger.info(`[ScaleBun Replay] finalize failure`);
306
- }).finally(() => {
307
- this._stopFlushTimer();
308
- // Keep the row-ready gate OPEN for a merged analytics session. The analytics
309
- // lane still owns it (not finalized on background — the session spans the
310
- // app-switch), so a foreground restart re-adopts the SAME id and must keep
311
- // flushing frames/events. Dropping the gate here would 404-buffer everything
312
- // after the first background cycle. Only clear it for a distinct/legacy
313
- // recording id that was actually finalized above.
314
- if (!(this.config.clientKey && session.sessionId === this._analyticsSessionId)) {
315
- this._startedSessionIds.delete(session.sessionId);
316
- }
317
- // Session end: drain any durably-stored telemetry from the native outbox.
318
- this._triggerNativeFlush();
319
- logger.debug(`[BackendSessionAdapter] Session finalized: ${session.sessionId}`);
320
- });
321
- }
322
-
323
- // ─── Analytics Lane (isolated from recording) ───────────────────────
324
-
325
- /** Public: the always-on analytics session id, or null before it opens. */
326
- get analyticsSessionId(): string | null {
327
- return this._analyticsSessionId;
328
- }
329
-
330
- /**
331
- * Open the always-on analytics ingestion session. Sets the analytics id,
332
- * starts the analytics flush timer, replays any pre-ready buffered events,
333
- * and POSTs INGESTION_START. Mirrors sendSessionStart's body builder but
334
- * never touches currentSessionId (recording lane).
335
- */
336
- async startAnalyticsSession(session: {
337
- sessionId: string;
338
- deviceId: string;
339
- startedAt: number;
340
- metadata?: SessionMetadata;
341
- /** Idle-gap threshold (ms) the SDK declares for this session; echoed by the
342
- * backend so the dashboard uses the same value to draw idle bands. */
343
- idleThresholdMs?: number;
344
- }): Promise<void> {
345
- if (this.destroyed) return;
346
- this._analyticsSessionId = session.sessionId;
347
- this._startAnalyticsFlushTimer();
348
-
349
- // Replay pre-ready buffered events now that the id exists. sessionId is
350
- // stamped at flush time, so buffered events need no rewrite.
351
- this._flushAnalyticsEvents().catch(() => { });
352
-
353
- const startEndpoint = this.config.clientKey ? ENDPOINTS.INGESTION_START : '/replay/sessions';
354
- try {
355
- const nativeInfo = await bridgeAdapter.getDeviceInfo();
356
- const m = session.metadata;
357
- const payload = {
358
- sessionId: session.sessionId,
359
- deviceId: session.deviceId,
360
- startedAt: session.startedAt,
361
- idleThresholdMs: session.idleThresholdMs,
362
- device: {
363
- platform: nativeInfo?.platform ?? m?.platform,
364
- osVersion: nativeInfo?.osVersion ?? m?.osVersion,
365
- deviceModel: nativeInfo?.deviceModel ?? m?.deviceModel,
366
- screenWidth: m?.screenWidth,
367
- screenHeight: m?.screenHeight,
368
- appName: nativeInfo?.appName ?? m?.appName,
369
- appVersion: nativeInfo?.appVersion ?? m?.appVersion,
370
- bundleId: nativeInfo?.bundleId ?? m?.bundleId,
371
- sdkVersion: SDK_VERSION,
372
- releaseStage: m?.buildType,
373
- environment: m?.buildType,
374
- },
375
- };
376
- await this._post(startEndpoint, payload);
377
- // §11: row exists. When recording adopts this analytics id (one-row merge),
378
- // this also releases the recording child-lane gate (_sessionRowReady).
379
- this._startedSessionIds.add(session.sessionId);
380
- // Row is confirmed — replay any events buffered while START was in flight.
381
- // The pre-ack flush at the top of this method is gated off until now, so
382
- // this is what actually drains the pre-ready buffer (no premature 404).
383
- this._flushAnalyticsEvents().catch(() => { });
384
- logger.info(`[ScaleBun Analytics] session start upload success: ${session.sessionId}`);
385
- } catch {
386
- logger.info(`[ScaleBun Analytics] session start upload failure`);
387
- }
388
- }
389
-
390
- /**
391
- * Enqueue a user track() event. Buffers (bounded, drop-oldest) when the
392
- * analytics session is not yet open; flushes at >=20 once it is.
393
- */
394
- trackEvent(event: JourneyEvent): void {
395
- if (this.destroyed) return;
396
- this.pendingAnalyticsEvents.push(event);
397
- const overflow = this.pendingAnalyticsEvents.length - BackendSessionAdapter.ANALYTICS_BUFFER_CAP;
398
- if (overflow > 0) {
399
- this.pendingAnalyticsEvents.splice(0, overflow); // drop oldest
400
- }
401
- if (this._analyticsSessionId && this.pendingAnalyticsEvents.length >= 20) {
402
- this._flushAnalyticsEvents().catch(() => { });
403
- }
404
- }
405
-
406
- /**
407
- * Emit an app-lifecycle boundary marker (APP_BACKGROUND / APP_FOREGROUND) onto
408
- * the analytics lane so the dashboard can shade the backgrounded span on the
409
- * replay timeline and exclude it from the active duration. Timestamp is captured
410
- * at the transition (accurate even if delivery is deferred until the next
411
- * foreground on iOS). No-op when no analytics session is open. The sessionId is
412
- * (re)stamped at flush time, so passing the current id here is only a placeholder.
413
- */
414
- emitLifecycleMarker(
415
- type: 'APP_BACKGROUND' | 'APP_FOREGROUND',
416
- payload?: Record<string, unknown>,
417
- ): void {
418
- if (this.destroyed || !this._analyticsSessionId) return;
419
- this.trackEvent({
420
- eventId: this._clientId(),
421
- sessionId: this._analyticsSessionId,
422
- ts: Date.now(),
423
- type,
424
- source: 'sdk',
425
- ...(payload ? { payload } : {}),
426
- });
427
- }
428
-
429
- /**
430
- * Public: force-flush queued analytics events immediately. Called on
431
- * APP_BACKGROUND so the lifecycle marker (and any buffered track events) reach
432
- * the backend before the OS suspends the flush timer. Best-effort on iOS, where
433
- * the POST may not resolve until the next foreground — the events stay buffered
434
- * with accurate timestamps and flush then.
435
- */
436
- flushAnalytics(): Promise<void> {
437
- return this._flushAnalyticsEvents();
438
- }
439
-
440
- /**
441
- * Flush queued analytics events. Mirrors _flushEvents (recording) byte for
442
- * byte on the wire map, but gates on _analyticsSessionId and STAMPS that id
443
- * into every event so endpoint id == body sessionId by construction.
444
- */
445
- private async _flushAnalyticsEvents(forSessionId?: string): Promise<void> {
446
- // finalize clears _analyticsSessionId synchronously, then passes the
447
- // captured id here so the final drain still targets the right session.
448
- const sessionId = forSessionId ?? this._analyticsSessionId;
449
- if (this.pendingAnalyticsEvents.length === 0 || !sessionId) return;
450
-
451
- // Row-confirmed gate (mirrors the recording lanes' _sessionRowReady). The
452
- // INGESTION_START create is async and can fail/lag; flushing events before
453
- // the row exists 404s the child write and re-buffers forever. Keep events
454
- // queued (bounded, drop-oldest via trackEvent) until START is acked.
455
- if (!this._startedSessionIds.has(sessionId)) return;
456
-
457
- const batch = this.pendingAnalyticsEvents.splice(0, 20);
458
- const events = batch.map(e => this._leanEvent(e, sessionId));
459
-
460
- try {
461
- const eventsEndpoint = this.config.clientKey
462
- ? ENDPOINTS.INGESTION_EVENTS(sessionId)
463
- : `/replay/sessions/${sessionId}/events`;
464
- await this._post(eventsEndpoint, { events });
465
- logger.debug(`[BackendSessionAdapter] Flushed ${batch.length} analytics event(s)`);
466
- } catch (err) {
467
- if (!BackendSessionAdapter._isPermanentHttpError(err)) this.pendingAnalyticsEvents.unshift(...batch);
468
- }
469
- }
470
-
471
- /** Flush remaining analytics events, finalize the session, stop its timer. */
472
- async finalizeAnalyticsSession(): Promise<void> {
473
- const sessionId = this._analyticsSessionId;
474
- if (!sessionId) return;
475
-
476
- // Clear the id and stop the timer SYNCHRONOUSLY, before any await. On iOS
477
- // the app is suspended on background and the finalize fetch below never
478
- // resolves until the next foreground, so the old `finally` that nulled the
479
- // id never ran before the resume guard (SDKBootstrapper: `state==='active'
480
- // && !adapter.analyticsSessionId`) evaluated → guard stayed false → no new
481
- // session opened. Clearing up front makes the guard always see null after
482
- // background, so resume re-opens a fresh analytics session every cycle.
483
- this._analyticsSessionId = null;
484
- this._stopAnalyticsFlushTimer();
485
-
486
- // Mark as pending-finalize BEFORE any await. On iOS the app suspends right
487
- // after backgrounding, so the awaited _post below may never resolve. Setting
488
- // the marker synchronously guarantees the next foreground can reconcile-close
489
- // this id even though the background POST was suspended. Cleared only on a
490
- // confirmed ACK (below), so a suspended POST leaves the marker in place.
491
- this._pendingFinalizeId = sessionId;
492
-
493
- try {
494
- // Pass the captured id explicitly — the field is already cleared.
495
- await this._flushAnalyticsEvents(sessionId);
496
- const finalizeEndpoint = this.config.clientKey
497
- ? ENDPOINTS.INGESTION_FINALIZE(sessionId)
498
- : `/replay/sessions/${sessionId}/finalize`;
499
- await this._post(finalizeEndpoint, { endedAt: Date.now() });
500
- // Confirmed delivered → drop the marker so the foreground reconciler does
501
- // NOT re-finalize this id (first half of the no-double-finalize guard).
502
- if (this._pendingFinalizeId === sessionId) this._pendingFinalizeId = null;
503
- logger.debug(`[BackendSessionAdapter] Analytics session finalized: ${sessionId}`);
504
- } catch {
505
- // Leave the marker set — foreground reconciliation will retry the close.
506
- logger.info(`[ScaleBun Analytics] finalize failure (will reconcile on foreground): ${sessionId}`);
507
- }
508
- }
509
-
510
- /**
511
- * Close any analytics session left open by a suspended background finalize.
512
- * Called on the NEXT foreground (SDKBootstrapper app-state 'active') BEFORE a new
513
- * analytics session is opened. JS is live on foreground, so this POST completes.
514
- * No-op when there is no pending id. Idempotent with the background finalize: the
515
- * marker is cleared on a confirmed background ACK, so this only fires when the
516
- * background POST was NOT confirmed; if that suspended POST later also lands, the
517
- * server must treat a repeat INGESTION_FINALIZE for the same id as a no-op.
518
- */
519
- async reconcilePendingFinalize(): Promise<void> {
520
- const sessionId = this._pendingFinalizeId;
521
- if (!sessionId) return;
522
-
523
- try {
524
- const finalizeEndpoint = this.config.clientKey
525
- ? ENDPOINTS.INGESTION_FINALIZE(sessionId)
526
- : `/replay/sessions/${sessionId}/finalize`;
527
- await this._post(finalizeEndpoint, { endedAt: Date.now() });
528
- logger.info(`[ScaleBun Analytics] reconciled finalize on foreground: ${sessionId}`);
529
- } catch {
530
- logger.info(`[ScaleBun Analytics] foreground reconcile finalize failed: ${sessionId}`);
531
- } finally {
532
- // Clear after a foreground attempt regardless of outcome: JS is live here
533
- // so a transient network error is rare, and the server-side idle-close
534
- // backstop covers any still-orphaned row. Bounds total finalizes per id to
535
- // at most 2 (suspended-bg + foreground) — never a per-foreground loop.
536
- if (this._pendingFinalizeId === sessionId) this._pendingFinalizeId = null;
537
- }
538
- }
539
-
540
- private _startAnalyticsFlushTimer(): void {
541
- this._stopAnalyticsFlushTimer();
542
- this.analyticsFlushTimer = setInterval(() => {
543
- this._flushAnalyticsEvents().catch(() => { });
544
- }, this.config.flushIntervalMs);
545
- }
546
-
547
- private _stopAnalyticsFlushTimer(): void {
548
- if (this.analyticsFlushTimer) {
549
- clearInterval(this.analyticsFlushTimer);
550
- this.analyticsFlushTimer = null;
551
- }
552
- }
553
-
554
- sendEvent(event: JourneyEvent): void {
555
- if (this.destroyed) return;
556
-
557
- logger.info(`[ScaleBun Replay] event recorded`);
558
- logger.info(` eventId: ${event.eventId}`);
559
- logger.info(` type: ${event.type}`);
560
- logger.info(` timestamp: ${event.ts}`);
561
- logger.info(` sessionId: ${event.sessionId}`);
562
-
563
- this.pendingEvents.push(event);
564
-
565
- if (this.pendingEvents.length >= 20) {
566
- this._flushEvents().catch(() => { });
567
- }
568
- }
569
-
570
- sendFrame(frame: ReplayFrame, imageData: string): void {
571
- if (this.destroyed) return;
572
-
573
- logger.info(`[ScaleBun Replay] frame captured`);
574
- logger.info(` frameId: ${frame.frameId}`);
575
- logger.info(` timestamp: ${frame.ts}`);
576
- logger.info(` sessionId: ${frame.sessionId}`);
577
- logger.info(` width/height: ${frame.width}x${frame.height}`);
578
-
579
- this.pendingFrames.push({ frame, imageData });
580
-
581
- if (this.pendingFrames.length >= this.config.batchSize) {
582
- this._flushFrames().catch(() => { });
583
- }
584
- }
585
-
586
- // ─── SaaS Ingestion Queues ──────────────────────────────────────────
587
-
588
- queueNetworkRequest(data: {
589
- method: string; url: string; statusCode?: number; duration?: number;
590
- screenName?: string; error?: string; requestSize?: number; responseSize?: number;
591
- requestHeaders?: Record<string, string>; responseHeaders?: Record<string, string>;
592
- }): void {
593
- if (this.destroyed || !this.config.clientKey) return;
594
- // clientId: stable per-row idempotency key so a mobile retry of the same
595
- // batch upserts instead of inserting duplicates server-side.
596
- this.pendingNetworkRequests.push({ ...data, clientId: this._clientId(), timestamp: new Date().toISOString() });
597
- if (this.pendingNetworkRequests.length >= 20) {
598
- this._flushNetwork().catch(() => {});
599
- }
600
- }
601
-
602
- queueError(data: {
603
- type: string; message: string; stack?: string; screenName?: string;
604
- }): void {
605
- if (this.destroyed || !this.config.clientKey) return;
606
- this.pendingErrors.push({ ...data, clientId: this._clientId(), timestamp: new Date().toISOString() });
607
- if (this.pendingErrors.length >= 10) {
608
- this._flushErrors().catch(() => {});
609
- }
610
- }
611
-
612
- /** Public: force-flush queued errors immediately (handled-error delivery). */
613
- flushErrors(): Promise<void> {
614
- return this._flushErrors();
615
- }
616
-
617
- /**
618
- * Public: flush ALL recording-lane queues immediately. Called on APP_BACKGROUND
619
- * so the server-side reaper computes endedAt from the freshest data even when
620
- * the OS suspends the flush timer right after backgrounding.
621
- */
622
- async flushAll(): Promise<void> {
623
- await Promise.all([
624
- this._flushFrames(),
625
- this._flushEvents(),
626
- this._flushNetwork(),
627
- this._flushErrors(),
628
- this._flushPerformance(),
629
- this._flushLogs(),
630
- ]);
631
- // Background trigger: close native segments + drain the native uploader so a
632
- // suspended JS context doesn't strand durably-stored telemetry.
633
- this._triggerNativeFlush();
634
- }
635
-
636
- queuePerformanceMetric(data: {
637
- type: string; screenName?: string; duration?: number; value?: number;
638
- metadata?: Record<string, unknown>;
639
- }): void {
640
- if (this.destroyed || !this.config.clientKey) return;
641
- this.pendingPerformanceMetrics.push({ ...data, clientId: this._clientId(), timestamp: new Date().toISOString() });
642
- if (this.pendingPerformanceMetrics.length >= 20) {
643
- this._flushPerformance().catch(() => {});
644
- }
645
- }
646
-
647
- /**
648
- * Queue one log line onto the platform-agnostic logs lane. Mirrors
649
- * queueNetworkRequest: drop when not in SaaS mode (no clientKey) or destroyed,
650
- * batch-flush at LOGS_BATCH_SIZE. The producer supplies source/platform/level —
651
- * this method makes NO assumptions about them, so a native producer reuses it as-is.
652
- */
653
- queueLog(data: {
654
- level: string; message: string; source: string; platform: string;
655
- timestamp?: string; metadata?: Record<string, unknown>;
656
- }): void {
657
- if (this.destroyed || !this.config.clientKey) return;
658
- this.pendingLogs.push({
659
- level: data.level,
660
- message: data.message,
661
- source: data.source,
662
- platform: data.platform,
663
- timestamp: data.timestamp ?? new Date().toISOString(),
664
- ...(data.metadata ? { metadata: data.metadata } : {}),
665
- });
666
- if (this.pendingLogs.length >= BackendSessionAdapter.LOGS_BATCH_SIZE) {
667
- this._flushLogs().catch(() => {});
668
- }
669
- }
670
-
671
- /** Stable client-generated idempotency id (matches journeyManager id scheme). */
672
- private _clientId(): string {
673
- return `${Date.now().toString(36)}-${Math.random().toString(36).substring(2, 10)}`;
674
- }
675
-
676
- // ─── Native outbox routing ──────────────────────────────────────────
677
-
678
- /**
679
- * Hand a telemetry batch to the durable native outbox. Returns true if native
680
- * accepted it (native uploader now owns delivery — caller must NOT also POST).
681
- * Returns false on any miss (flag off, no session, old binary, native error) so
682
- * the caller falls back to the JS HTTP path with the batch intact.
683
- */
684
- private async _enqueueNative(
685
- lane: 'events' | 'network' | 'errors' | 'performance' | 'logs',
686
- records: Array<Record<string, unknown>>,
687
- ): Promise<boolean> {
688
- if (!this.nativeOutboxEnabled || !this.currentSessionId) return false;
689
- const native = getReplaySdkNative();
690
- if (!native?.enqueueOutboxRecords) return false;
691
- if (!(await this._ensureNativeOutbox(native))) return false;
692
- try {
693
- return await native.enqueueOutboxRecords(lane, this.currentSessionId, records);
694
- } catch {
695
- return false;
696
- }
697
- }
698
-
699
- /**
700
- * Bootstrap the native outbox once. In SaaS mode the native module's full
701
- * `initialize()` (which builds a SessionManager) is never called, so the
702
- * NativeOutbox/uploader would not exist. `initOutbox` constructs only the
703
- * durable outbox from clientKey/apiBaseUrl/flags. Idempotent + cached so it
704
- * runs at most once; resolves false on old binaries (caller falls back to JS).
705
- */
706
- private _ensureNativeOutbox(native: ReplaySdkNativeModule): Promise<boolean> {
707
- if (this._nativeOutboxReady) return this._nativeOutboxReady;
708
- if (!native.initOutbox) return Promise.resolve(false);
709
- this._nativeOutboxReady = native
710
- .initOutbox({
711
- ...this.config.nativeOutboxTuning,
712
- clientKey: this.config.clientKey,
713
- apiBaseUrl: this.config.endpoint,
714
- enableNativeFileOutbox: true,
715
- nativeOutboxUploadEnabled: true,
716
- useObjectStorageForFrames: this.config.useObjectStorage === true,
717
- })
718
- .catch(() => false);
719
- return this._nativeOutboxReady;
720
- }
721
-
722
- /**
723
- * Public readiness gate for the native frame outbox path (used by the frame
724
- * capture adapter). Resolves true only when both outbox flags are on, a session
725
- * exists, the native binary exposes the bridge, and `initOutbox` succeeded.
726
- * Resolves false otherwise so the frame pipeline falls back to `captureScreenshot`.
727
- */
728
- ensureNativeOutboxReady(): Promise<boolean> {
729
- if (!this.nativeOutboxEnabled || !this.currentSessionId) return Promise.resolve(false);
730
- const native = getReplaySdkNative();
731
- if (!native?.captureScreenshotToFile) return Promise.resolve(false);
732
- return this._ensureNativeOutbox(native);
733
- }
734
-
735
- /** Best-effort: close native segments and drain the native uploader. Never throws. */
736
- private _triggerNativeFlush(): void {
737
- if (!this.nativeOutboxEnabled) return;
738
- try {
739
- getReplaySdkNative()?.flushNativeOutbox?.().catch(() => { });
740
- } catch {
741
- /* old binary / unavailable — ignore */
742
- }
743
- }
744
-
745
- // ─── Lifecycle ──────────────────────────────────────────────────────
746
-
747
- destroy(): void {
748
- this.destroyed = true;
749
- this._stopFlushTimer();
750
- this._stopAnalyticsFlushTimer();
751
- this.pendingFrames = [];
752
- this.pendingEvents = [];
753
- this.pendingAnalyticsEvents = [];
754
- this.pendingNetworkRequests = [];
755
- this.pendingErrors = [];
756
- this.pendingPerformanceMetrics = [];
757
- this.currentSessionId = null;
758
- this._analyticsSessionId = null;
759
- this._pendingFinalizeId = null;
760
- this._startedSessionIds.clear();
761
- }
762
-
763
- // ─── Internal: Flush ────────────────────────────────────────────────
764
-
765
- /** Wire metadata for a frame — real format/sizeBytes from native (no hardcoded literals). */
766
- private _frameMeta(b: { frame: ReplayFrame; imageData: string }) {
767
- const f = b.frame;
768
- const format = f.format ?? 'jpeg';
769
- // P2-5: a JSON frame-delta carries an application content type, not an image MIME.
770
- const isJsonDelta = f.frameType === 'delta' && format === 'scalebun-framedelta';
771
- const contentType = isJsonDelta
772
- ? 'application/x-scalebun-framedelta+json'
773
- : `image/${format}`;
774
- return {
775
- frameId: f.frameId,
776
- sessionId: f.sessionId,
777
- timestamp: f.ts,
778
- // P2-0: real monotonic per-session sequence (was hardcoded 0 server-side).
779
- sequenceNumber: f.sequenceNumber,
780
- // P2-5: keyframe|delta + base reference for dashboard reconstruction.
781
- frameType: f.frameType,
782
- baseFrameId: f.baseFrameId,
783
- screenName: f.screen ?? '',
784
- trigger: f.captureReason ?? '',
785
- format,
786
- contentType,
787
- width: f.width,
788
- height: f.height,
789
- sizeBytes: f.byteSize ?? 0,
790
- masked: f.redactionState === 'full',
791
- };
792
- }
793
-
794
- /**
795
- * P2-4: build the lean (v2) wire payload for one event. Drops redundant/empty
796
- * fields at the source while NEVER dropping fields the dashboard/analytics depend
797
- * on (eventId, type, timestamp, sessionId). `label` is omitted when it equals
798
- * `type` (the server defaults it back). `screenName` omitted when empty. `data`
799
- * is pruned of null/''/undefined leaves (one level). The `v:2` marker lets the
800
- * backend/dashboard pick the lean decoder; legacy (v1/no-marker) events still
801
- * decode unchanged. See P2_CONTRACT.md §4.
802
- */
803
- private _leanEvent(e: JourneyEvent, sessionId: string): Record<string, unknown> {
804
- const out: Record<string, unknown> = {
805
- v: 2,
806
- eventId: e.eventId,
807
- sessionId,
808
- type: e.type,
809
- timestamp: e.ts,
810
- };
811
- const screen = e.screen ?? '';
812
- if (screen) out.screenName = screen;
813
- const label = e.subtype ?? e.type;
814
- if (label && label !== e.type) out.label = label;
815
- const data = this._pruneEmpty(e.payload);
816
- if (data && Object.keys(data).length > 0) out.data = data;
817
- return out;
818
- }
819
-
820
- /** Shallow-prune null/undefined/'' leaves from a payload object. */
821
- private _pruneEmpty(payload: unknown): Record<string, unknown> | undefined {
822
- if (!payload || typeof payload !== 'object') return undefined;
823
- const src = payload as Record<string, unknown>;
824
- const out: Record<string, unknown> = {};
825
- for (const k of Object.keys(src)) {
826
- const v = src[k];
827
- if (v === null || v === undefined || v === '') continue;
828
- out[k] = v;
829
- }
830
- return out;
831
- }
832
-
833
- private async _flushFrames(): Promise<void> {
834
- if (this.pendingFrames.length === 0 || !this.currentSessionId) return;
835
- // §11: hold frames until the session_start row is confirmed (else 404). Data stays
836
- // buffered; the flush timer retries once the row lands.
837
- if (!this._sessionRowReady()) return;
838
- const sessionId = this.currentSessionId;
839
-
840
- const batch = this.pendingFrames.splice(0, this.config.batchSize);
841
- try {
842
- await this._postFrameBatch(sessionId, batch);
843
- logger.debug(`[BackendSessionAdapter] Flushed ${batch.length} frame(s)`);
844
- // Delivered — the durable snapshot (if any) is now redundant. Clear it once
845
- // the in-memory buffer is fully drained so a later kill can't replay
846
- // already-uploaded frames.
847
- if (this.pendingFrames.length === 0) this._clearPersistedFrames();
848
- } catch (err) {
849
- if (BackendSessionAdapter._isPermanentHttpError(err)) return;
850
- logger.warn(`[replay.sdk.error] backend frame upload failure`, { count: batch.length });
851
- // Re-queue on failure
852
- this.pendingFrames.unshift(...batch);
853
- }
854
- }
855
-
856
- /**
857
- * POST one frame batch under an EXPLICIT sessionId (object-storage path when
858
- * active, else legacy inline base64). Used by both the live flush and cross-kill
859
- * recovery — recovery passes the PRIOR session's id so orphaned frames relink to
860
- * it. Throws on transient error so the caller can re-queue; frame writes are
861
- * idempotent server-side (upsert by frameId), so a double-send is harmless.
862
- */
863
- private async _postFrameBatch(
864
- sessionId: string,
865
- batch: Array<{ frame: ReplayFrame; imageData: string }>,
866
- ): Promise<void> {
867
- if (batch.length === 0) return;
868
- logger.info(`[replay.sdk.frame] backend frame upload started`, { count: batch.length });
869
-
870
- // Object-storage path: presign → PUT bytes → post key-only metadata.
871
- if (this.objectStorageActive && this.config.clientKey) {
872
- const result = await this._uploadFramesViaStorage(sessionId, batch);
873
- if (result === 'sent') {
874
- logger.info(`[replay.sdk.frame] backend frame upload success (object storage)`);
875
- return;
876
- }
877
- // 'disabled' → storage not configured server-side; fall through to inline.
878
- }
879
-
880
- // Legacy inline path: base64 in JSON body.
881
- const frames = batch.map(b => ({ ...this._frameMeta(b), imageData: b.imageData }));
882
- const framesEndpoint = this.config.clientKey
883
- ? ENDPOINTS.INGESTION_FRAMES(sessionId)
884
- : `/replay/sessions/${sessionId}/frames`;
885
- await this._post(framesEndpoint, { frames });
886
- logger.info(`[replay.sdk.frame] backend frame upload success`);
887
- }
888
-
889
- // ─── Cross-kill frame recovery ──────────────────────────────────────
890
- //
891
- // Frames buffer in-memory (pendingFrames) and only reach the backend on flush.
892
- // A process kill (swipe-away, OOM) between captures loses the last frames the
893
- // user saw — the iOS/Android background flush may be suspended before its POST
894
- // resolves. To close that gap we snapshot the unflushed buffer to the durable
895
- // KV store on background (survives kill), then re-upload it on the NEXT launch
896
- // linked to the PRIOR session id. Best-effort and never throws.
897
-
898
- /**
899
- * Snapshot the current unflushed frame buffer to durable storage so it survives
900
- * a process kill. Called on APP_BACKGROUND before the (possibly-suspended)
901
- * network flush. Synchronous mirror write — reaches disk on the native store's
902
- * next coalesced flush. No-op if recovery storage is absent or nothing pending.
903
- */
904
- persistPendingFrames(): void {
905
- if (!this._frameStore || this.destroyed || !this.currentSessionId) return;
906
- if (this.pendingFrames.length === 0) return;
907
- try {
908
- const items = this.pendingFrames.slice(-BackendSessionAdapter.MAX_PERSIST_FRAMES);
909
- this._frameStore.set(
910
- BackendSessionAdapter.PENDING_FRAMES_KEY,
911
- JSON.stringify({ sessionId: this.currentSessionId, items }),
912
- );
913
- } catch {
914
- // Serialization/storage failure must never break backgrounding.
915
- }
916
- }
917
-
918
- /** Drop the persisted frame snapshot (after successful delivery). Never throws. */
919
- private _clearPersistedFrames(): void {
920
- if (!this._frameStore) return;
921
- try {
922
- this._frameStore.delete(BackendSessionAdapter.PENDING_FRAMES_KEY);
923
- } catch {
924
- /* non-fatal */
925
- }
926
- }
927
-
928
- /**
929
- * On cold launch: if a prior run left an unflushed frame snapshot, re-upload it
930
- * linked to that PRIOR session, then clear it. Runs independently of the new
931
- * session (uses the stored id + a direct POST, bypassing the row-ready gate —
932
- * the prior session row already exists server-side). Best-effort; on transient
933
- * failure the snapshot is kept for the next launch.
934
- */
935
- async recoverPersistedFrames(): Promise<void> {
936
- if (!this._frameStore) return;
937
- let raw: string | undefined;
938
- try {
939
- raw = this._frameStore.get(BackendSessionAdapter.PENDING_FRAMES_KEY);
940
- } catch {
941
- return;
942
- }
943
- if (!raw) return;
944
-
945
- let parsed: { sessionId?: string; items?: Array<{ frame: ReplayFrame; imageData: string }> };
946
- try {
947
- parsed = JSON.parse(raw);
948
- } catch {
949
- // Corrupt snapshot — discard so it can't wedge every launch.
950
- this._clearPersistedFrames();
951
- return;
952
- }
953
-
954
- const sessionId = parsed.sessionId;
955
- const items = parsed.items;
956
- if (!sessionId || !Array.isArray(items) || items.length === 0) {
957
- this._clearPersistedFrames();
958
- return;
959
- }
960
-
961
- try {
962
- logger.info(`[replay.sdk.frame] recovering ${items.length} frame(s) for prior session ${sessionId}`);
963
- await this._postFrameBatch(sessionId, items);
964
- this._clearPersistedFrames();
965
- } catch (err) {
966
- if (BackendSessionAdapter._isPermanentHttpError(err)) {
967
- // Server rejected permanently (e.g. session gone) — don't retry forever.
968
- this._clearPersistedFrames();
969
- return;
970
- }
971
- // Transient — keep the snapshot for the next launch.
972
- logger.warn(`[replay.sdk.frame] prior-session frame recovery deferred (transient)`);
973
- }
974
- }
975
-
976
- /**
977
- * Upload a batch via object storage. Returns 'sent' on success, 'disabled' if
978
- * the backend reports storage is not configured (caller falls back to inline).
979
- * Throws on transient error so the caller re-queues the batch.
980
- */
981
- private async _uploadFramesViaStorage(
982
- sessionId: string,
983
- batch: Array<{ frame: ReplayFrame; imageData: string }>,
984
- ): Promise<'sent' | 'disabled'> {
985
- const presignReq = batch.map(b => {
986
- const m = this._frameMeta(b);
987
- return { frameId: m.frameId, contentType: m.contentType, format: m.format };
988
- });
989
- const resp = await this._postReturning<{ enabled: boolean; frames: Array<{ frameId: string; uploadUrl: string; storageKey: string; bucket: string; contentType: string }> }>(
990
- ENDPOINTS.INGESTION_FRAMES_PRESIGN(sessionId),
991
- { frames: presignReq },
992
- );
993
-
994
- if (!resp || resp.enabled === false) {
995
- // Latch off for the rest of the session so we don't presign every batch.
996
- this.objectStorageActive = false;
997
- return 'disabled';
998
- }
999
-
1000
- const byFrameId = new Map(resp.frames.map(p => [p.frameId, p]));
1001
-
1002
- // Upload bytes directly to storage (backend never sees image bytes here).
1003
- await Promise.all(batch.map(async b => {
1004
- const p = byFrameId.get(b.frame.frameId);
1005
- if (!p) throw new Error(`No presign URL for frame ${b.frame.frameId}`);
1006
- await this._putBytes(p.uploadUrl, b.imageData, p.contentType);
1007
- }));
1008
-
1009
- // Persist key-only metadata (no base64 in the body).
1010
- const frames = batch.map(b => {
1011
- const p = byFrameId.get(b.frame.frameId)!;
1012
- return { ...this._frameMeta(b), storageKey: p.storageKey, contentType: p.contentType };
1013
- });
1014
- await this._post(ENDPOINTS.INGESTION_FRAMES(sessionId), { frames });
1015
- return 'sent';
1016
- }
1017
-
1018
- private async _flushEvents(): Promise<void> {
1019
- if (this.pendingEvents.length === 0 || !this.currentSessionId) return;
1020
-
1021
- const batch = this.pendingEvents.splice(0, 20);
1022
- const events = batch.map(e => this._leanEvent(e, e.sessionId));
1023
-
1024
- try {
1025
- logger.info(`[replay.sdk.event] backend event upload started`, { count: batch.length });
1026
- // Durable native outbox owns delivery when active (no duplicate JS POST).
1027
- // The native enqueue is NOT gated on row-readiness: it writes to disk and its
1028
- // uploader handles ordering/retry, so it must accept data even while offline.
1029
- if (await this._enqueueNative('events', events)) return;
1030
- // §11: JS-direct POST only after the session_start row exists; else re-buffer.
1031
- if (!this._sessionRowReady()) { this.pendingEvents.unshift(...batch); return; }
1032
- const eventsEndpoint = this.config.clientKey
1033
- ? ENDPOINTS.INGESTION_EVENTS(this.currentSessionId)
1034
- : `/replay/sessions/${this.currentSessionId}/events`;
1035
- await this._post(
1036
- eventsEndpoint,
1037
- { events },
1038
- );
1039
- logger.info(`[replay.sdk.event] backend event upload success`);
1040
- logger.debug(`[BackendSessionAdapter] Flushed ${batch.length} event(s)`);
1041
- } catch (err) {
1042
- if (BackendSessionAdapter._isPermanentHttpError(err)) return;
1043
- logger.warn(`[replay.sdk.error] backend event upload failure`, { count: batch.length });
1044
- this.pendingEvents.unshift(...batch);
1045
- }
1046
- }
1047
-
1048
- private async _flushNetwork(): Promise<void> {
1049
- if (this.pendingNetworkRequests.length === 0 || !this.currentSessionId || !this.config.clientKey) return;
1050
- const batch = this.pendingNetworkRequests.splice(0, 50);
1051
- try {
1052
- if (await this._enqueueNative('network', batch)) return;
1053
- if (!this._sessionRowReady()) { this.pendingNetworkRequests.unshift(...batch); return; }
1054
- await this._post(ENDPOINTS.INGESTION_NETWORK(this.currentSessionId), { requests: batch });
1055
- } catch (err) {
1056
- if (!BackendSessionAdapter._isPermanentHttpError(err)) this.pendingNetworkRequests.unshift(...batch);
1057
- }
1058
- }
1059
-
1060
- private async _flushErrors(): Promise<void> {
1061
- if (this.pendingErrors.length === 0 || !this.currentSessionId || !this.config.clientKey) return;
1062
- const batch = this.pendingErrors.splice(0, 20);
1063
- try {
1064
- if (await this._enqueueNative('errors', batch)) return;
1065
- if (!this._sessionRowReady()) { this.pendingErrors.unshift(...batch); return; }
1066
- await this._post(ENDPOINTS.INGESTION_ERRORS(this.currentSessionId), { errors: batch });
1067
- } catch (err) {
1068
- if (!BackendSessionAdapter._isPermanentHttpError(err)) this.pendingErrors.unshift(...batch);
1069
- }
1070
- }
1071
-
1072
- private async _flushPerformance(): Promise<void> {
1073
- if (this.pendingPerformanceMetrics.length === 0 || !this.currentSessionId || !this.config.clientKey) return;
1074
- const batch = this.pendingPerformanceMetrics.splice(0, 50);
1075
- try {
1076
- if (await this._enqueueNative('performance', batch)) return;
1077
- if (!this._sessionRowReady()) { this.pendingPerformanceMetrics.unshift(...batch); return; }
1078
- await this._post(ENDPOINTS.INGESTION_PERFORMANCE(this.currentSessionId), { metrics: batch });
1079
- } catch (err) {
1080
- if (!BackendSessionAdapter._isPermanentHttpError(err)) this.pendingPerformanceMetrics.unshift(...batch);
1081
- }
1082
- }
1083
-
1084
- private async _flushLogs(): Promise<void> {
1085
- if (this.pendingLogs.length === 0 || !this.currentSessionId || !this.config.clientKey) return;
1086
- const batch = this.pendingLogs.splice(0, BackendSessionAdapter.LOGS_FLUSH_MAX);
1087
- try {
1088
- if (await this._enqueueNative('logs', batch as unknown as Array<Record<string, unknown>>)) return;
1089
- if (!this._sessionRowReady()) { this.pendingLogs.unshift(...batch); return; }
1090
- await this._post(ENDPOINTS.INGESTION_LOGS(this.currentSessionId), { logs: batch });
1091
- } catch (err) {
1092
- if (!BackendSessionAdapter._isPermanentHttpError(err)) this.pendingLogs.unshift(...batch);
1093
- }
1094
- }
1095
-
1096
- // ─── Internal: Timer ────────────────────────────────────────────────
1097
-
1098
- private _startFlushTimer(): void {
1099
- this._stopFlushTimer();
1100
- this.flushTimer = setInterval(() => {
1101
- this._flushFrames().catch(() => { });
1102
- this._flushEvents().catch(() => { });
1103
- this._flushNetwork().catch(() => { });
1104
- this._flushErrors().catch(() => { });
1105
- this._flushPerformance().catch(() => { });
1106
- this._flushLogs().catch(() => { });
1107
- this._triggerNativeFlush();
1108
- }, this.config.flushIntervalMs);
1109
- }
1110
-
1111
- private _stopFlushTimer(): void {
1112
- if (this.flushTimer) {
1113
- clearInterval(this.flushTimer);
1114
- this.flushTimer = null;
1115
- }
1116
- }
1117
-
1118
- // ─── Internal: HTTP ─────────────────────────────────────────────────
1119
-
1120
- // A 4xx (except 408 Request Timeout / 429 Too Many Requests) is permanent:
1121
- // the same payload will never succeed, so requeuing it retries forever and
1122
- // floods the logs (e.g. a rejected clientKey → HTTP 403 on every flush tick).
1123
- // Drop the batch on these; keep retrying 5xx / timeouts / network errors.
1124
- private static _isPermanentHttpError(err: unknown): boolean {
1125
- const status = (err as { status?: number })?.status;
1126
- return typeof status === 'number' && status >= 400 && status < 500 && status !== 408 && status !== 429;
1127
- }
1128
-
1129
- private async _post(path: string, body: unknown): Promise<void> {
1130
- const url = `${this.config.endpoint}${path}`;
1131
-
1132
- try {
1133
- const controller = new AbortController();
1134
- const timeout = setTimeout(() => controller.abort(), this.config.timeoutMs);
1135
-
1136
- try {
1137
- const headers: Record<string, string> = { 'Content-Type': 'application/json' };
1138
- if (this.config.clientKey) {
1139
- headers['x-scalebun-client-key'] = this.config.clientKey;
1140
- }
1141
- const response = await fetch(url, {
1142
- method: 'POST',
1143
- headers,
1144
- body: JSON.stringify(body),
1145
- signal: controller.signal,
1146
- });
1147
-
1148
- if (!response.ok) {
1149
- logger.warn(`[BackendSessionAdapter] HTTP ${response.status} from ${path}`);
1150
- const httpErr = new Error(`HTTP ${response.status}`) as Error & { status?: number };
1151
- httpErr.status = response.status;
1152
- throw httpErr;
1153
- }
1154
- } finally {
1155
- clearTimeout(timeout);
1156
- }
1157
- } catch (err: any) {
1158
- if (err?.name === 'AbortError') {
1159
- logger.warn(`[BackendSessionAdapter] Timeout on ${path}`);
1160
- } else {
1161
- logger.warn(`[BackendSessionAdapter] Failed ${path}: ${err?.message}`);
1162
- }
1163
- throw err;
1164
- }
1165
- }
1166
-
1167
- /**
1168
- * POST that parses and returns the JSON response body. Mirrors _post's headers
1169
- * and timeout handling; used by the object-storage presign request, which needs
1170
- * the returned upload URLs (the void _post discards the body).
1171
- */
1172
- private async _postReturning<T>(path: string, body: unknown): Promise<T> {
1173
- const url = `${this.config.endpoint}${path}`;
1174
-
1175
- const controller = new AbortController();
1176
- const timeout = setTimeout(() => controller.abort(), this.config.timeoutMs);
1177
- try {
1178
- const headers: Record<string, string> = { 'Content-Type': 'application/json' };
1179
- if (this.config.clientKey) {
1180
- headers['x-scalebun-client-key'] = this.config.clientKey;
1181
- }
1182
- const response = await fetch(url, {
1183
- method: 'POST',
1184
- headers,
1185
- body: JSON.stringify(body),
1186
- signal: controller.signal,
1187
- });
1188
- if (!response.ok) {
1189
- logger.warn(`[BackendSessionAdapter] HTTP ${response.status} from ${path}`);
1190
- const httpErr = new Error(`HTTP ${response.status}`) as Error & { status?: number };
1191
- httpErr.status = response.status;
1192
- throw httpErr;
1193
- }
1194
- return (await response.json()) as T;
1195
- } finally {
1196
- clearTimeout(timeout);
1197
- }
1198
- }
1199
-
1200
- /**
1201
- * PUT raw image bytes directly to a presigned storage URL. Decodes the base64
1202
- * frame payload to a binary Blob so the wire body is bytes, not a base64 string.
1203
- * No client key header — the presigned URL carries its own auth.
1204
- */
1205
- private async _putBytes(uploadUrl: string, base64: string, contentType: string): Promise<void> {
1206
- // RN-safe base64→binary: decode to a Uint8Array and send that as the body.
1207
- // The `fetch('data:…').blob()` round-trip fails under the new architecture
1208
- // ("Network request failed"); RN's XHR sends a typed array as real binary.
1209
- const bytes = base64ToBytes(this._stripDataUri(base64));
1210
-
1211
- const controller = new AbortController();
1212
- const timeout = setTimeout(() => controller.abort(), this.config.timeoutMs);
1213
- try {
1214
- const response = await fetch(uploadUrl, {
1215
- method: 'PUT',
1216
- headers: { 'Content-Type': contentType },
1217
- body: bytes,
1218
- signal: controller.signal,
1219
- });
1220
- if (!response.ok) {
1221
- throw new Error(`HTTP ${response.status}`);
1222
- }
1223
- } finally {
1224
- clearTimeout(timeout);
1225
- }
1226
- }
1227
-
1228
- /** Strip a leading `data:<mime>;base64,` prefix if the native layer included one. */
1229
- private _stripDataUri(s: string): string {
1230
- const comma = s.indexOf(',');
1231
- return s.startsWith('data:') && comma !== -1 ? s.slice(comma + 1) : s;
1232
- }
1233
- }
1
+ /**
2
+ * ScaleBun SDK — Backend Session Adapter
3
+ *
4
+ * Implements the SessionTransport interface (System A) and bridges
5
+ * session/frame/event data to the backend API via HTTP.
6
+ *
7
+ * This is the ADAPTER that connects the existing SessionManager
8
+ * (which only has DesktopSessionTransport) to the backend.
9
+ *
10
+ * Design:
11
+ * - Uses the same endpoint contract as BackendReplayTransport
12
+ * (POST /v1/replay/sessions, /frames, /events, /finalize)
13
+ * - Batches frames and events with auto-flush
14
+ * - Never throws — all errors are caught and logged
15
+ * - Behind config flag: only constructed when backendUpload is enabled
16
+ *
17
+ * This does NOT duplicate the existing BackendReplayTransport.
18
+ * It exists because SessionManager uses a different interface
19
+ * (SessionTransport from sessionTypes.ts) than ReplayTransport
20
+ * (from features/replay/transport/ReplayTransport.ts).
21
+ * The payload shapes differ, so this adapter maps between them.
22
+ *
23
+ * MVP/dev-only: base64 frames are sent inline in JSON body.
24
+ */
25
+
26
+ import { logger } from '../../core/logger/internalLogger';
27
+ import { base64ToBytes } from '../../core/encoding/base64';
28
+ import { ENDPOINTS } from '../../transport/http/endpoints';
29
+ import { SDK_VERSION } from '../../core/constants/version';
30
+ import { bridgeAdapter } from '../replay/bridge/adapters/bridgeAdapter';
31
+ import { getReplaySdkNative } from '../replay/bridge/nativeModule';
32
+ import type { ReplaySdkNativeModule } from '../replay/bridge/nativeModule';
33
+ import type { StorageBackend } from '../../storage/StorageBackend';
34
+ import type {
35
+ SessionTransport,
36
+ Session,
37
+ SessionMetadata,
38
+ JourneyEvent,
39
+ ReplayFrame,
40
+ } from './sessionTypes';
41
+
42
+ // ─── Config ─────────────────────────────────────────────────────────────────
43
+
44
+ export interface BackendSessionConfig {
45
+ /** Backend API base URL (e.g. http://localhost:3001/api) */
46
+ endpoint: string;
47
+ /** Batch size for frames before auto-flush. Default: 5 */
48
+ batchSize?: number;
49
+ /** Auto-flush interval in ms. Default: 3000 */
50
+ flushIntervalMs?: number;
51
+ /** Request timeout in ms. Default: 15000 */
52
+ timeoutMs?: number;
53
+ /** SaaS multi-tenant client key — enables ingestion endpoints and x-scalebun-client-key header */
54
+ clientKey?: string;
55
+ /**
56
+ * Upload frame bytes directly to object storage via presigned PUT instead of
57
+ * inline base64 in the JSON body. Default false → legacy inline path. Flip on
58
+ * after the backend presign endpoint is deployed. Falls back to inline
59
+ * automatically if the backend reports storage is not configured.
60
+ */
61
+ useObjectStorage?: boolean;
62
+ /**
63
+ * Route telemetry lanes (events/network/errors/performance/logs) through the
64
+ * durable NATIVE file outbox instead of JS-side HTTP. Only takes effect when BOTH
65
+ * this and `nativeOutboxUploadEnabled` are true AND the native module exposes the
66
+ * outbox methods — otherwise the existing JS upload path is used unchanged. When
67
+ * active, the native uploader owns delivery (no duplicate JS POST). Default false.
68
+ */
69
+ enableNativeFileOutbox?: boolean;
70
+ /** Native outbox actually uploads (vs. capture/store-only). Gates telemetry routing. */
71
+ nativeOutboxUploadEnabled?: boolean;
72
+ /**
73
+ * Additive native-outbox tuning flags (retry interval, attempt caps, Retry-After,
74
+ * byte/age GC bounds, etc.) forwarded verbatim to the native `initOutbox` dict.
75
+ * Native parses both `nativeOutbox*` and bare `outbox*` keys and applies its own
76
+ * defaults for anything omitted — so an empty object changes nothing.
77
+ */
78
+ nativeOutboxTuning?: Record<string, unknown>;
79
+ /** Idle-gap threshold (ms) the SDK recorded with; persisted on the session row. */
80
+ idleThresholdMs?: number;
81
+ /**
82
+ * Durable key-value store used to persist the unflushed frame buffer across a
83
+ * process kill. On background the in-flight frames are snapshotted here; on the
84
+ * next launch they are re-uploaded and linked to the PRIOR session. Omitted →
85
+ * frame-kill recovery is disabled (in-memory only, prior behavior).
86
+ */
87
+ storage?: StorageBackend;
88
+ }
89
+
90
+ /**
91
+ * One platform-agnostic log line for the logs lane. The queue forwards whatever it is
92
+ * given — `source`/`platform` are neutral string hints set by the PRODUCER (console
93
+ * tags 'console'/'js'; a future native producer tags its own values onto this SAME
94
+ * shape). `level` is free-text. Nothing here is JS-specific.
95
+ */
96
+ export interface LogQueueItem {
97
+ level: string;
98
+ message: string;
99
+ source: string;
100
+ platform: string;
101
+ timestamp: string;
102
+ metadata?: Record<string, unknown>;
103
+ }
104
+
105
+ // ─── Adapter ────────────────────────────────────────────────────────────────
106
+
107
+ export class BackendSessionAdapter implements SessionTransport {
108
+ private config: Required<Omit<BackendSessionConfig, 'clientKey' | 'storage'>> & { clientKey?: string; storage?: StorageBackend };
109
+ /** Durable store for cross-kill frame recovery (null → recovery disabled). */
110
+ private readonly _frameStore: StorageBackend | null;
111
+ /** Storage key for the snapshotted unflushed frame buffer (see persistPendingFrames). */
112
+ private static readonly PENDING_FRAMES_KEY = 'scalebun_replay_pending_frames';
113
+ /** Cap on frames persisted per snapshot — bounds KV footprint (keeps the most recent). */
114
+ private static readonly MAX_PERSIST_FRAMES = 10;
115
+ // Per-session toggle: cleared to false if the backend reports storage disabled.
116
+ private objectStorageActive: boolean;
117
+ // True when telemetry should divert to the durable native outbox (both flags on).
118
+ // Native module availability is re-checked per call so a missing/old binary falls
119
+ // back to the JS path transparently.
120
+ private readonly nativeOutboxEnabled: boolean;
121
+ // Cached one-shot native-outbox bootstrap promise (see _ensureNativeOutbox).
122
+ private _nativeOutboxReady: Promise<boolean> | null = null;
123
+ private currentSessionId: string | null = null;
124
+ // §11 session_start ordering: a recording sessionId is added here ONLY after its
125
+ // INGESTION_START row is confirmed created on the backend (either via sendSessionStart's
126
+ // own POST, or via startAnalyticsSession when recording adopts the analytics id).
127
+ // Child telemetry lanes (frames/events/network/errors/perf/logs) refuse to flush until
128
+ // the row exists — otherwise the backend 404s the child write. Data stays buffered and
129
+ // the flush timer retries, so nothing is lost to a start/child race. The durable native
130
+ // outbox path has its own ordering; this guards only the JS in-memory fallback.
131
+ private readonly _startedSessionIds = new Set<string>();
132
+ private pendingFrames: Array<{ frame: ReplayFrame; imageData: string }> = [];
133
+ private pendingEvents: JourneyEvent[] = [];
134
+ private pendingNetworkRequests: Array<Record<string, unknown>> = [];
135
+ private pendingErrors: Array<Record<string, unknown>> = [];
136
+ private pendingPerformanceMetrics: Array<Record<string, unknown>> = [];
137
+ // Platform-agnostic logs lane. Neutral by construction — holds whatever LogQueueItems
138
+ // it's handed (console today; native later) and forwards them untouched.
139
+ private pendingLogs: LogQueueItem[] = [];
140
+ private flushTimer: ReturnType<typeof setInterval> | null = null;
141
+ private destroyed = false;
142
+
143
+ // ── Analytics lane (always-on, foreground-scoped; isolated from recording) ──
144
+ // Fully separate from currentSessionId/pendingEvents/_flushEvents, which serve
145
+ // recording. This lane carries user track() events and never touches recording
146
+ // state. One queue doubles as the pre-ready buffer (bounded, drop-oldest) and
147
+ // the outgoing queue; sessionId is stamped at flush so endpoint id == body id.
148
+ private static readonly ANALYTICS_BUFFER_CAP = 100;
149
+ /** Logs lane: queue length that triggers an eager flush (mirrors the network lane). */
150
+ private static readonly LOGS_BATCH_SIZE = 20;
151
+ /** Logs lane: max rows posted per flush (server caps at 200/batch). */
152
+ private static readonly LOGS_FLUSH_MAX = 50;
153
+ private _analyticsSessionId: string | null = null;
154
+ private pendingAnalyticsEvents: JourneyEvent[] = [];
155
+ private analyticsFlushTimer: ReturnType<typeof setInterval> | null = null;
156
+ // iOS finalize reconciliation: the id of a backgrounded analytics session whose
157
+ // INGESTION_FINALIZE has NOT been confirmed delivered. Set synchronously in
158
+ // finalizeAnalyticsSession before any await (so it survives an iOS suspension of
159
+ // the awaited fetch), cleared only on a confirmed finalize ACK. On the next
160
+ // foreground the listener calls reconcilePendingFinalize() to close it for real.
161
+ // In-memory is sufficient: the JS context survives background→foreground; only a
162
+ // true process kill drops it (covered by the server-side idle-close backstop).
163
+ private _pendingFinalizeId: string | null = null;
164
+
165
+ constructor(config: BackendSessionConfig) {
166
+ this.config = {
167
+ batchSize: 5,
168
+ flushIntervalMs: 3000,
169
+ timeoutMs: 15_000,
170
+ useObjectStorage: false,
171
+ enableNativeFileOutbox: false,
172
+ nativeOutboxUploadEnabled: false,
173
+ nativeOutboxTuning: {},
174
+ idleThresholdMs: 60_000,
175
+ ...config,
176
+ clientKey: config.clientKey,
177
+ };
178
+ this._frameStore = config.storage ?? null;
179
+ this.objectStorageActive = this.config.useObjectStorage;
180
+ this.nativeOutboxEnabled =
181
+ this.config.enableNativeFileOutbox && this.config.nativeOutboxUploadEnabled;
182
+ logger.info(`[ScaleBun Replay] backendUpload enabled`);
183
+ logger.info(`[ScaleBun Replay] backendBaseUrl: ${this.config.endpoint}`);
184
+ logger.info(`[ScaleBun Replay] transport fan-out active: desktop yes, backend yes`);
185
+ }
186
+
187
+ // ─── SessionTransport Interface ─────────────────────────────────────
188
+
189
+ /**
190
+ * §11 gate: true only when the current recording session's INGESTION_START row is
191
+ * confirmed on the backend. Child telemetry lanes consult this before flushing so they
192
+ * never race ahead of session creation (which would 404). Null id → not ready.
193
+ */
194
+ private _sessionRowReady(): boolean {
195
+ return !!this.currentSessionId && this._startedSessionIds.has(this.currentSessionId);
196
+ }
197
+
198
+ sendSessionStart(session: Session): void {
199
+ this.currentSessionId = session.sessionId;
200
+ this._startFlushTimer();
201
+
202
+ logger.info(`[ScaleBun Replay] session start requested`);
203
+ logger.info(`[ScaleBun Replay] sessionId: ${session.sessionId}`);
204
+ logger.info(`[ScaleBun Replay] deviceId: ${session.deviceId}`);
205
+ logger.info(`[ScaleBun Replay] recordingSessionId: ${session.sessionId}`);
206
+
207
+ // One-row merge: when recording adopted the always-on analytics id
208
+ // (SessionManager.startSession), the INGESTION_START row already exists.
209
+ // Do NOT post a second one — just keep the flush timer running so frames/
210
+ // journey/network/errors/perf flush to INGESTION_*(analyticsId). Legacy
211
+ // mode (no clientKey, distinct minted id) still posts /replay/sessions.
212
+ if (this.config.clientKey && session.sessionId === this._analyticsSessionId) {
213
+ logger.info(`[ScaleBun Replay] recording attached to analytics session ${session.sessionId} (no new row)`);
214
+ return;
215
+ }
216
+
217
+ logger.info(`[ScaleBun Replay] backend session upload started`);
218
+
219
+ const startEndpoint = this.config.clientKey ? ENDPOINTS.INGESTION_START : '/replay/sessions';
220
+
221
+ // Fetch native device info to enrich the session payload.
222
+ // Falls back to metadata-only if bridge unavailable (old native binary).
223
+ bridgeAdapter.getDeviceInfo()
224
+ .then(nativeInfo => {
225
+ const m = session.metadata;
226
+ const payload = {
227
+ sessionId: session.sessionId,
228
+ deviceId: session.deviceId,
229
+ startedAt: session.startedAt,
230
+ // Link the recording row to the always-on analytics row so the
231
+ // dashboard can join them. track() events land on the analytics
232
+ // id; frames/journey land on this recording id. Without this
233
+ // link the two appear as separate sessions (one looks "empty").
234
+ // BACKEND DEPENDENCY: the dashboard must read/join on this field
235
+ // (or treat the analytics row as canonical) to fully merge them.
236
+ analyticsSessionId: this._analyticsSessionId,
237
+ // Carry the idle threshold on the recording lane too: it may
238
+ // create the row before the analytics lane does. Backend
239
+ // upsert leaves it untouched if already set.
240
+ idleThresholdMs: this.config.idleThresholdMs,
241
+ device: {
242
+ platform: nativeInfo?.platform ?? m?.platform,
243
+ osVersion: nativeInfo?.osVersion ?? m?.osVersion,
244
+ deviceModel: nativeInfo?.deviceModel ?? m?.deviceModel,
245
+ screenWidth: m?.screenWidth,
246
+ screenHeight: m?.screenHeight,
247
+ appName: nativeInfo?.appName ?? m?.appName,
248
+ appVersion: nativeInfo?.appVersion ?? m?.appVersion,
249
+ bundleId: nativeInfo?.bundleId ?? m?.bundleId,
250
+ sdkVersion: SDK_VERSION,
251
+ releaseStage: m?.buildType,
252
+ // Backend ingestion source not in this repo; field name
253
+ // unconfirmed. Send both so whichever it reads is populated.
254
+ environment: m?.buildType,
255
+ },
256
+ };
257
+ logger.debug(`[BackendSessionAdapter] POST session start: ${session.sessionId}`);
258
+ return this._post(startEndpoint, payload);
259
+ })
260
+ .then(() => {
261
+ // §11: row now exists — release the child-lane flush gate for this id.
262
+ this._startedSessionIds.add(session.sessionId);
263
+ logger.info(`[ScaleBun Replay] backend session upload success`);
264
+ })
265
+ .catch(() => logger.info(`[ScaleBun Replay] backend session upload failure`));
266
+ }
267
+
268
+ sendSessionEnd(session: Session): void {
269
+ logger.info(`[ScaleBun Replay] finalize started`);
270
+ // Flush all pending data first, then finalize
271
+ Promise.all([
272
+ this._flushFrames(),
273
+ this._flushEvents(),
274
+ this._flushNetwork(),
275
+ this._flushErrors(),
276
+ this._flushPerformance(),
277
+ ]).then(() => {
278
+ // One-row merge: if this recording adopted the always-on analytics id,
279
+ // the analytics lane owns the session's lifecycle and finalizes it on
280
+ // background (finalizeAnalyticsSession). Finalizing here would close the
281
+ // shared row mid-foreground and orphan later track() events — so flush
282
+ // (above) but skip finalize. Legacy/distinct-id sessions finalize normally.
283
+ if (this.config.clientKey && session.sessionId === this._analyticsSessionId) {
284
+ logger.info(`[ScaleBun Replay] recording ended; analytics session ${session.sessionId} stays open`);
285
+ return;
286
+ }
287
+ const finalizeEndpoint = this.config.clientKey
288
+ ? ENDPOINTS.INGESTION_FINALIZE(session.sessionId)
289
+ : `/replay/sessions/${session.sessionId}/finalize`;
290
+ return this._post(
291
+ finalizeEndpoint,
292
+ {
293
+ endedAt: session.endedAt ?? Date.now(),
294
+ durationMs: session.endedAt
295
+ ? session.endedAt - session.startedAt
296
+ : Date.now() - session.startedAt,
297
+ totalFrames: session.artifactIndex?.frameRefs?.length ?? 0,
298
+ totalEvents: session.artifactIndex?.eventRefs?.length ?? 0,
299
+ finalState: session.status === 'timeout' ? 'timeout' : 'completed',
300
+ },
301
+ );
302
+ }).then(() => {
303
+ logger.info(`[ScaleBun Replay] finalize success`);
304
+ }).catch(() => {
305
+ logger.info(`[ScaleBun Replay] finalize failure`);
306
+ }).finally(() => {
307
+ this._stopFlushTimer();
308
+ // Keep the row-ready gate OPEN for a merged analytics session. The analytics
309
+ // lane still owns it (not finalized on background — the session spans the
310
+ // app-switch), so a foreground restart re-adopts the SAME id and must keep
311
+ // flushing frames/events. Dropping the gate here would 404-buffer everything
312
+ // after the first background cycle. Only clear it for a distinct/legacy
313
+ // recording id that was actually finalized above.
314
+ if (!(this.config.clientKey && session.sessionId === this._analyticsSessionId)) {
315
+ this._startedSessionIds.delete(session.sessionId);
316
+ }
317
+ // Session end: drain any durably-stored telemetry from the native outbox.
318
+ this._triggerNativeFlush();
319
+ logger.debug(`[BackendSessionAdapter] Session finalized: ${session.sessionId}`);
320
+ });
321
+ }
322
+
323
+ // ─── Analytics Lane (isolated from recording) ───────────────────────
324
+
325
+ /** Public: the always-on analytics session id, or null before it opens. */
326
+ get analyticsSessionId(): string | null {
327
+ return this._analyticsSessionId;
328
+ }
329
+
330
+ /**
331
+ * Open the always-on analytics ingestion session. Sets the analytics id,
332
+ * starts the analytics flush timer, replays any pre-ready buffered events,
333
+ * and POSTs INGESTION_START. Mirrors sendSessionStart's body builder but
334
+ * never touches currentSessionId (recording lane).
335
+ */
336
+ async startAnalyticsSession(session: {
337
+ sessionId: string;
338
+ deviceId: string;
339
+ startedAt: number;
340
+ metadata?: SessionMetadata;
341
+ /** Idle-gap threshold (ms) the SDK declares for this session; echoed by the
342
+ * backend so the dashboard uses the same value to draw idle bands. */
343
+ idleThresholdMs?: number;
344
+ }): Promise<void> {
345
+ if (this.destroyed) return;
346
+ this._analyticsSessionId = session.sessionId;
347
+ this._startAnalyticsFlushTimer();
348
+
349
+ // Replay pre-ready buffered events now that the id exists. sessionId is
350
+ // stamped at flush time, so buffered events need no rewrite.
351
+ this._flushAnalyticsEvents().catch(() => { });
352
+
353
+ const startEndpoint = this.config.clientKey ? ENDPOINTS.INGESTION_START : '/replay/sessions';
354
+ try {
355
+ const nativeInfo = await bridgeAdapter.getDeviceInfo();
356
+ const m = session.metadata;
357
+ const payload = {
358
+ sessionId: session.sessionId,
359
+ deviceId: session.deviceId,
360
+ startedAt: session.startedAt,
361
+ idleThresholdMs: session.idleThresholdMs,
362
+ device: {
363
+ platform: nativeInfo?.platform ?? m?.platform,
364
+ osVersion: nativeInfo?.osVersion ?? m?.osVersion,
365
+ deviceModel: nativeInfo?.deviceModel ?? m?.deviceModel,
366
+ screenWidth: m?.screenWidth,
367
+ screenHeight: m?.screenHeight,
368
+ appName: nativeInfo?.appName ?? m?.appName,
369
+ appVersion: nativeInfo?.appVersion ?? m?.appVersion,
370
+ bundleId: nativeInfo?.bundleId ?? m?.bundleId,
371
+ sdkVersion: SDK_VERSION,
372
+ releaseStage: m?.buildType,
373
+ environment: m?.buildType,
374
+ },
375
+ };
376
+ await this._post(startEndpoint, payload);
377
+ // §11: row exists. When recording adopts this analytics id (one-row merge),
378
+ // this also releases the recording child-lane gate (_sessionRowReady).
379
+ this._startedSessionIds.add(session.sessionId);
380
+ // Row is confirmed — replay any events buffered while START was in flight.
381
+ // The pre-ack flush at the top of this method is gated off until now, so
382
+ // this is what actually drains the pre-ready buffer (no premature 404).
383
+ this._flushAnalyticsEvents().catch(() => { });
384
+ logger.info(`[ScaleBun Analytics] session start upload success: ${session.sessionId}`);
385
+ } catch {
386
+ logger.info(`[ScaleBun Analytics] session start upload failure`);
387
+ }
388
+ }
389
+
390
+ /**
391
+ * Enqueue a user track() event. Buffers (bounded, drop-oldest) when the
392
+ * analytics session is not yet open; flushes at >=20 once it is.
393
+ */
394
+ trackEvent(event: JourneyEvent): void {
395
+ if (this.destroyed) return;
396
+ this.pendingAnalyticsEvents.push(event);
397
+ const overflow = this.pendingAnalyticsEvents.length - BackendSessionAdapter.ANALYTICS_BUFFER_CAP;
398
+ if (overflow > 0) {
399
+ this.pendingAnalyticsEvents.splice(0, overflow); // drop oldest
400
+ }
401
+ if (this._analyticsSessionId && this.pendingAnalyticsEvents.length >= 20) {
402
+ this._flushAnalyticsEvents().catch(() => { });
403
+ }
404
+ }
405
+
406
+ /**
407
+ * Emit an app-lifecycle boundary marker (APP_BACKGROUND / APP_FOREGROUND) onto
408
+ * the analytics lane so the dashboard can shade the backgrounded span on the
409
+ * replay timeline and exclude it from the active duration. Timestamp is captured
410
+ * at the transition (accurate even if delivery is deferred until the next
411
+ * foreground on iOS). No-op when no analytics session is open. The sessionId is
412
+ * (re)stamped at flush time, so passing the current id here is only a placeholder.
413
+ */
414
+ emitLifecycleMarker(
415
+ type: 'APP_BACKGROUND' | 'APP_FOREGROUND',
416
+ payload?: Record<string, unknown>,
417
+ ): void {
418
+ if (this.destroyed || !this._analyticsSessionId) return;
419
+ this.trackEvent({
420
+ eventId: this._clientId(),
421
+ sessionId: this._analyticsSessionId,
422
+ ts: Date.now(),
423
+ type,
424
+ source: 'sdk',
425
+ ...(payload ? { payload } : {}),
426
+ });
427
+ }
428
+
429
+ /**
430
+ * Public: force-flush queued analytics events immediately. Called on
431
+ * APP_BACKGROUND so the lifecycle marker (and any buffered track events) reach
432
+ * the backend before the OS suspends the flush timer. Best-effort on iOS, where
433
+ * the POST may not resolve until the next foreground — the events stay buffered
434
+ * with accurate timestamps and flush then.
435
+ */
436
+ flushAnalytics(): Promise<void> {
437
+ return this._flushAnalyticsEvents();
438
+ }
439
+
440
+ /**
441
+ * Flush queued analytics events. Mirrors _flushEvents (recording) byte for
442
+ * byte on the wire map, but gates on _analyticsSessionId and STAMPS that id
443
+ * into every event so endpoint id == body sessionId by construction.
444
+ */
445
+ private async _flushAnalyticsEvents(forSessionId?: string): Promise<void> {
446
+ // finalize clears _analyticsSessionId synchronously, then passes the
447
+ // captured id here so the final drain still targets the right session.
448
+ const sessionId = forSessionId ?? this._analyticsSessionId;
449
+ if (this.pendingAnalyticsEvents.length === 0 || !sessionId) return;
450
+
451
+ // Row-confirmed gate (mirrors the recording lanes' _sessionRowReady). The
452
+ // INGESTION_START create is async and can fail/lag; flushing events before
453
+ // the row exists 404s the child write and re-buffers forever. Keep events
454
+ // queued (bounded, drop-oldest via trackEvent) until START is acked.
455
+ if (!this._startedSessionIds.has(sessionId)) return;
456
+
457
+ const batch = this.pendingAnalyticsEvents.splice(0, 20);
458
+ const events = batch.map(e => this._leanEvent(e, sessionId));
459
+
460
+ try {
461
+ const eventsEndpoint = this.config.clientKey
462
+ ? ENDPOINTS.INGESTION_EVENTS(sessionId)
463
+ : `/replay/sessions/${sessionId}/events`;
464
+ await this._post(eventsEndpoint, { events });
465
+ logger.debug(`[BackendSessionAdapter] Flushed ${batch.length} analytics event(s)`);
466
+ } catch (err) {
467
+ if (!BackendSessionAdapter._isPermanentHttpError(err)) this.pendingAnalyticsEvents.unshift(...batch);
468
+ }
469
+ }
470
+
471
+ /** Flush remaining analytics events, finalize the session, stop its timer. */
472
+ async finalizeAnalyticsSession(): Promise<void> {
473
+ const sessionId = this._analyticsSessionId;
474
+ if (!sessionId) return;
475
+
476
+ // Clear the id and stop the timer SYNCHRONOUSLY, before any await. On iOS
477
+ // the app is suspended on background and the finalize fetch below never
478
+ // resolves until the next foreground, so the old `finally` that nulled the
479
+ // id never ran before the resume guard (SDKBootstrapper: `state==='active'
480
+ // && !adapter.analyticsSessionId`) evaluated → guard stayed false → no new
481
+ // session opened. Clearing up front makes the guard always see null after
482
+ // background, so resume re-opens a fresh analytics session every cycle.
483
+ this._analyticsSessionId = null;
484
+ this._stopAnalyticsFlushTimer();
485
+
486
+ // Mark as pending-finalize BEFORE any await. On iOS the app suspends right
487
+ // after backgrounding, so the awaited _post below may never resolve. Setting
488
+ // the marker synchronously guarantees the next foreground can reconcile-close
489
+ // this id even though the background POST was suspended. Cleared only on a
490
+ // confirmed ACK (below), so a suspended POST leaves the marker in place.
491
+ this._pendingFinalizeId = sessionId;
492
+
493
+ try {
494
+ // Pass the captured id explicitly — the field is already cleared.
495
+ await this._flushAnalyticsEvents(sessionId);
496
+ const finalizeEndpoint = this.config.clientKey
497
+ ? ENDPOINTS.INGESTION_FINALIZE(sessionId)
498
+ : `/replay/sessions/${sessionId}/finalize`;
499
+ await this._post(finalizeEndpoint, { endedAt: Date.now() });
500
+ // Confirmed delivered → drop the marker so the foreground reconciler does
501
+ // NOT re-finalize this id (first half of the no-double-finalize guard).
502
+ if (this._pendingFinalizeId === sessionId) this._pendingFinalizeId = null;
503
+ logger.debug(`[BackendSessionAdapter] Analytics session finalized: ${sessionId}`);
504
+ } catch {
505
+ // Leave the marker set — foreground reconciliation will retry the close.
506
+ logger.info(`[ScaleBun Analytics] finalize failure (will reconcile on foreground): ${sessionId}`);
507
+ }
508
+ }
509
+
510
+ /**
511
+ * Close any analytics session left open by a suspended background finalize.
512
+ * Called on the NEXT foreground (SDKBootstrapper app-state 'active') BEFORE a new
513
+ * analytics session is opened. JS is live on foreground, so this POST completes.
514
+ * No-op when there is no pending id. Idempotent with the background finalize: the
515
+ * marker is cleared on a confirmed background ACK, so this only fires when the
516
+ * background POST was NOT confirmed; if that suspended POST later also lands, the
517
+ * server must treat a repeat INGESTION_FINALIZE for the same id as a no-op.
518
+ */
519
+ async reconcilePendingFinalize(): Promise<void> {
520
+ const sessionId = this._pendingFinalizeId;
521
+ if (!sessionId) return;
522
+
523
+ try {
524
+ const finalizeEndpoint = this.config.clientKey
525
+ ? ENDPOINTS.INGESTION_FINALIZE(sessionId)
526
+ : `/replay/sessions/${sessionId}/finalize`;
527
+ await this._post(finalizeEndpoint, { endedAt: Date.now() });
528
+ logger.info(`[ScaleBun Analytics] reconciled finalize on foreground: ${sessionId}`);
529
+ } catch {
530
+ logger.info(`[ScaleBun Analytics] foreground reconcile finalize failed: ${sessionId}`);
531
+ } finally {
532
+ // Clear after a foreground attempt regardless of outcome: JS is live here
533
+ // so a transient network error is rare, and the server-side idle-close
534
+ // backstop covers any still-orphaned row. Bounds total finalizes per id to
535
+ // at most 2 (suspended-bg + foreground) — never a per-foreground loop.
536
+ if (this._pendingFinalizeId === sessionId) this._pendingFinalizeId = null;
537
+ }
538
+ }
539
+
540
+ private _startAnalyticsFlushTimer(): void {
541
+ this._stopAnalyticsFlushTimer();
542
+ this.analyticsFlushTimer = setInterval(() => {
543
+ this._flushAnalyticsEvents().catch(() => { });
544
+ }, this.config.flushIntervalMs);
545
+ }
546
+
547
+ private _stopAnalyticsFlushTimer(): void {
548
+ if (this.analyticsFlushTimer) {
549
+ clearInterval(this.analyticsFlushTimer);
550
+ this.analyticsFlushTimer = null;
551
+ }
552
+ }
553
+
554
+ sendEvent(event: JourneyEvent): void {
555
+ if (this.destroyed) return;
556
+
557
+ logger.info(`[ScaleBun Replay] event recorded`);
558
+ logger.info(` eventId: ${event.eventId}`);
559
+ logger.info(` type: ${event.type}`);
560
+ logger.info(` timestamp: ${event.ts}`);
561
+ logger.info(` sessionId: ${event.sessionId}`);
562
+
563
+ this.pendingEvents.push(event);
564
+
565
+ if (this.pendingEvents.length >= 20) {
566
+ this._flushEvents().catch(() => { });
567
+ }
568
+ }
569
+
570
+ sendFrame(frame: ReplayFrame, imageData: string): void {
571
+ if (this.destroyed) return;
572
+
573
+ logger.info(`[ScaleBun Replay] frame captured`);
574
+ logger.info(` frameId: ${frame.frameId}`);
575
+ logger.info(` timestamp: ${frame.ts}`);
576
+ logger.info(` sessionId: ${frame.sessionId}`);
577
+ logger.info(` width/height: ${frame.width}x${frame.height}`);
578
+
579
+ this.pendingFrames.push({ frame, imageData });
580
+
581
+ if (this.pendingFrames.length >= this.config.batchSize) {
582
+ this._flushFrames().catch(() => { });
583
+ }
584
+ }
585
+
586
+ // ─── SaaS Ingestion Queues ──────────────────────────────────────────
587
+
588
+ queueNetworkRequest(data: {
589
+ method: string; url: string; statusCode?: number; duration?: number;
590
+ screenName?: string; error?: string; requestSize?: number; responseSize?: number;
591
+ requestHeaders?: Record<string, string>; responseHeaders?: Record<string, string>;
592
+ }): void {
593
+ if (this.destroyed || !this.config.clientKey) return;
594
+ // clientId: stable per-row idempotency key so a mobile retry of the same
595
+ // batch upserts instead of inserting duplicates server-side.
596
+ this.pendingNetworkRequests.push({ ...data, clientId: this._clientId(), timestamp: new Date().toISOString() });
597
+ if (this.pendingNetworkRequests.length >= 20) {
598
+ this._flushNetwork().catch(() => {});
599
+ }
600
+ }
601
+
602
+ queueError(data: {
603
+ type: string; message: string; stack?: string; screenName?: string;
604
+ }): void {
605
+ if (this.destroyed || !this.config.clientKey) return;
606
+ this.pendingErrors.push({ ...data, clientId: this._clientId(), timestamp: new Date().toISOString() });
607
+ if (this.pendingErrors.length >= 10) {
608
+ this._flushErrors().catch(() => {});
609
+ }
610
+ }
611
+
612
+ /** Public: force-flush queued errors immediately (handled-error delivery). */
613
+ flushErrors(): Promise<void> {
614
+ return this._flushErrors();
615
+ }
616
+
617
+ /**
618
+ * Public: flush ALL recording-lane queues immediately. Called on APP_BACKGROUND
619
+ * so the server-side reaper computes endedAt from the freshest data even when
620
+ * the OS suspends the flush timer right after backgrounding.
621
+ */
622
+ async flushAll(): Promise<void> {
623
+ await Promise.all([
624
+ this._flushFrames(),
625
+ this._flushEvents(),
626
+ this._flushNetwork(),
627
+ this._flushErrors(),
628
+ this._flushPerformance(),
629
+ this._flushLogs(),
630
+ ]);
631
+ // Background trigger: close native segments + drain the native uploader so a
632
+ // suspended JS context doesn't strand durably-stored telemetry.
633
+ this._triggerNativeFlush();
634
+ }
635
+
636
+ queuePerformanceMetric(data: {
637
+ type: string; screenName?: string; duration?: number; value?: number;
638
+ metadata?: Record<string, unknown>;
639
+ }): void {
640
+ if (this.destroyed || !this.config.clientKey) return;
641
+ this.pendingPerformanceMetrics.push({ ...data, clientId: this._clientId(), timestamp: new Date().toISOString() });
642
+ if (this.pendingPerformanceMetrics.length >= 20) {
643
+ this._flushPerformance().catch(() => {});
644
+ }
645
+ }
646
+
647
+ /**
648
+ * Queue one log line onto the platform-agnostic logs lane. Mirrors
649
+ * queueNetworkRequest: drop when not in SaaS mode (no clientKey) or destroyed,
650
+ * batch-flush at LOGS_BATCH_SIZE. The producer supplies source/platform/level —
651
+ * this method makes NO assumptions about them, so a native producer reuses it as-is.
652
+ */
653
+ queueLog(data: {
654
+ level: string; message: string; source: string; platform: string;
655
+ timestamp?: string; metadata?: Record<string, unknown>;
656
+ }): void {
657
+ if (this.destroyed || !this.config.clientKey) return;
658
+ this.pendingLogs.push({
659
+ level: data.level,
660
+ message: data.message,
661
+ source: data.source,
662
+ platform: data.platform,
663
+ timestamp: data.timestamp ?? new Date().toISOString(),
664
+ ...(data.metadata ? { metadata: data.metadata } : {}),
665
+ });
666
+ if (this.pendingLogs.length >= BackendSessionAdapter.LOGS_BATCH_SIZE) {
667
+ this._flushLogs().catch(() => {});
668
+ }
669
+ }
670
+
671
+ /** Stable client-generated idempotency id (matches journeyManager id scheme). */
672
+ private _clientId(): string {
673
+ return `${Date.now().toString(36)}-${Math.random().toString(36).substring(2, 10)}`;
674
+ }
675
+
676
+ // ─── Native outbox routing ──────────────────────────────────────────
677
+
678
+ /**
679
+ * Hand a telemetry batch to the durable native outbox. Returns true if native
680
+ * accepted it (native uploader now owns delivery — caller must NOT also POST).
681
+ * Returns false on any miss (flag off, no session, old binary, native error) so
682
+ * the caller falls back to the JS HTTP path with the batch intact.
683
+ */
684
+ private async _enqueueNative(
685
+ lane: 'events' | 'network' | 'errors' | 'performance' | 'logs',
686
+ records: Array<Record<string, unknown>>,
687
+ ): Promise<boolean> {
688
+ if (!this.nativeOutboxEnabled || !this.currentSessionId) return false;
689
+ const native = getReplaySdkNative();
690
+ if (!native?.enqueueOutboxRecords) return false;
691
+ if (!(await this._ensureNativeOutbox(native))) return false;
692
+ try {
693
+ return await native.enqueueOutboxRecords(lane, this.currentSessionId, records);
694
+ } catch {
695
+ return false;
696
+ }
697
+ }
698
+
699
+ /**
700
+ * Bootstrap the native outbox once. In SaaS mode the native module's full
701
+ * `initialize()` (which builds a SessionManager) is never called, so the
702
+ * NativeOutbox/uploader would not exist. `initOutbox` constructs only the
703
+ * durable outbox from clientKey/apiBaseUrl/flags. Idempotent + cached so it
704
+ * runs at most once; resolves false on old binaries (caller falls back to JS).
705
+ */
706
+ private _ensureNativeOutbox(native: ReplaySdkNativeModule): Promise<boolean> {
707
+ if (this._nativeOutboxReady) return this._nativeOutboxReady;
708
+ if (!native.initOutbox) return Promise.resolve(false);
709
+ this._nativeOutboxReady = native
710
+ .initOutbox({
711
+ ...this.config.nativeOutboxTuning,
712
+ clientKey: this.config.clientKey,
713
+ apiBaseUrl: this.config.endpoint,
714
+ enableNativeFileOutbox: true,
715
+ nativeOutboxUploadEnabled: true,
716
+ useObjectStorageForFrames: this.config.useObjectStorage === true,
717
+ })
718
+ .catch(() => false);
719
+ return this._nativeOutboxReady;
720
+ }
721
+
722
+ /**
723
+ * Public readiness gate for the native frame outbox path (used by the frame
724
+ * capture adapter). Resolves true only when both outbox flags are on, a session
725
+ * exists, the native binary exposes the bridge, and `initOutbox` succeeded.
726
+ * Resolves false otherwise so the frame pipeline falls back to `captureScreenshot`.
727
+ */
728
+ ensureNativeOutboxReady(): Promise<boolean> {
729
+ if (!this.nativeOutboxEnabled || !this.currentSessionId) return Promise.resolve(false);
730
+ const native = getReplaySdkNative();
731
+ if (!native?.captureScreenshotToFile) return Promise.resolve(false);
732
+ return this._ensureNativeOutbox(native);
733
+ }
734
+
735
+ /** Best-effort: close native segments and drain the native uploader. Never throws. */
736
+ private _triggerNativeFlush(): void {
737
+ if (!this.nativeOutboxEnabled) return;
738
+ try {
739
+ getReplaySdkNative()?.flushNativeOutbox?.().catch(() => { });
740
+ } catch {
741
+ /* old binary / unavailable — ignore */
742
+ }
743
+ }
744
+
745
+ // ─── Lifecycle ──────────────────────────────────────────────────────
746
+
747
+ destroy(): void {
748
+ this.destroyed = true;
749
+ this._stopFlushTimer();
750
+ this._stopAnalyticsFlushTimer();
751
+ this.pendingFrames = [];
752
+ this.pendingEvents = [];
753
+ this.pendingAnalyticsEvents = [];
754
+ this.pendingNetworkRequests = [];
755
+ this.pendingErrors = [];
756
+ this.pendingPerformanceMetrics = [];
757
+ this.currentSessionId = null;
758
+ this._analyticsSessionId = null;
759
+ this._pendingFinalizeId = null;
760
+ this._startedSessionIds.clear();
761
+ }
762
+
763
+ // ─── Internal: Flush ────────────────────────────────────────────────
764
+
765
+ /** Wire metadata for a frame — real format/sizeBytes from native (no hardcoded literals). */
766
+ private _frameMeta(b: { frame: ReplayFrame; imageData: string }) {
767
+ const f = b.frame;
768
+ const format = f.format ?? 'jpeg';
769
+ // P2-5: a JSON frame-delta carries an application content type, not an image MIME.
770
+ const isJsonDelta = f.frameType === 'delta' && format === 'scalebun-framedelta';
771
+ const contentType = isJsonDelta
772
+ ? 'application/x-scalebun-framedelta+json'
773
+ : `image/${format}`;
774
+ return {
775
+ frameId: f.frameId,
776
+ sessionId: f.sessionId,
777
+ timestamp: f.ts,
778
+ // P2-0: real monotonic per-session sequence (was hardcoded 0 server-side).
779
+ sequenceNumber: f.sequenceNumber,
780
+ // P2-5: keyframe|delta + base reference for dashboard reconstruction.
781
+ frameType: f.frameType,
782
+ baseFrameId: f.baseFrameId,
783
+ screenName: f.screen ?? '',
784
+ trigger: f.captureReason ?? '',
785
+ format,
786
+ contentType,
787
+ width: f.width,
788
+ height: f.height,
789
+ sizeBytes: f.byteSize ?? 0,
790
+ masked: f.redactionState === 'full',
791
+ };
792
+ }
793
+
794
+ /**
795
+ * P2-4: build the lean (v2) wire payload for one event. Drops redundant/empty
796
+ * fields at the source while NEVER dropping fields the dashboard/analytics depend
797
+ * on (eventId, type, timestamp, sessionId). `label` is omitted when it equals
798
+ * `type` (the server defaults it back). `screenName` omitted when empty. `data`
799
+ * is pruned of null/''/undefined leaves (one level). The `v:2` marker lets the
800
+ * backend/dashboard pick the lean decoder; legacy (v1/no-marker) events still
801
+ * decode unchanged. See P2_CONTRACT.md §4.
802
+ */
803
+ private _leanEvent(e: JourneyEvent, sessionId: string): Record<string, unknown> {
804
+ const out: Record<string, unknown> = {
805
+ v: 2,
806
+ eventId: e.eventId,
807
+ sessionId,
808
+ type: e.type,
809
+ timestamp: e.ts,
810
+ };
811
+ const screen = e.screen ?? '';
812
+ if (screen) out.screenName = screen;
813
+ const label = e.subtype ?? e.type;
814
+ if (label && label !== e.type) out.label = label;
815
+ const data = this._pruneEmpty(e.payload);
816
+ if (data && Object.keys(data).length > 0) out.data = data;
817
+ return out;
818
+ }
819
+
820
+ /** Shallow-prune null/undefined/'' leaves from a payload object. */
821
+ private _pruneEmpty(payload: unknown): Record<string, unknown> | undefined {
822
+ if (!payload || typeof payload !== 'object') return undefined;
823
+ const src = payload as Record<string, unknown>;
824
+ const out: Record<string, unknown> = {};
825
+ for (const k of Object.keys(src)) {
826
+ const v = src[k];
827
+ if (v === null || v === undefined || v === '') continue;
828
+ out[k] = v;
829
+ }
830
+ return out;
831
+ }
832
+
833
+ private async _flushFrames(): Promise<void> {
834
+ if (this.pendingFrames.length === 0 || !this.currentSessionId) return;
835
+ // §11: hold frames until the session_start row is confirmed (else 404). Data stays
836
+ // buffered; the flush timer retries once the row lands.
837
+ if (!this._sessionRowReady()) return;
838
+ const sessionId = this.currentSessionId;
839
+
840
+ const batch = this.pendingFrames.splice(0, this.config.batchSize);
841
+ try {
842
+ await this._postFrameBatch(sessionId, batch);
843
+ logger.debug(`[BackendSessionAdapter] Flushed ${batch.length} frame(s)`);
844
+ // Delivered — the durable snapshot (if any) is now redundant. Clear it once
845
+ // the in-memory buffer is fully drained so a later kill can't replay
846
+ // already-uploaded frames.
847
+ if (this.pendingFrames.length === 0) this._clearPersistedFrames();
848
+ } catch (err) {
849
+ if (BackendSessionAdapter._isPermanentHttpError(err)) return;
850
+ logger.warn(`[replay.sdk.error] backend frame upload failure`, { count: batch.length });
851
+ // Re-queue on failure
852
+ this.pendingFrames.unshift(...batch);
853
+ }
854
+ }
855
+
856
+ /**
857
+ * POST one frame batch under an EXPLICIT sessionId (object-storage path when
858
+ * active, else legacy inline base64). Used by both the live flush and cross-kill
859
+ * recovery — recovery passes the PRIOR session's id so orphaned frames relink to
860
+ * it. Throws on transient error so the caller can re-queue; frame writes are
861
+ * idempotent server-side (upsert by frameId), so a double-send is harmless.
862
+ */
863
+ private async _postFrameBatch(
864
+ sessionId: string,
865
+ batch: Array<{ frame: ReplayFrame; imageData: string }>,
866
+ ): Promise<void> {
867
+ if (batch.length === 0) return;
868
+ logger.info(`[replay.sdk.frame] backend frame upload started`, { count: batch.length });
869
+
870
+ // Object-storage path: presign → PUT bytes → post key-only metadata.
871
+ if (this.objectStorageActive && this.config.clientKey) {
872
+ const result = await this._uploadFramesViaStorage(sessionId, batch);
873
+ if (result === 'sent') {
874
+ logger.info(`[replay.sdk.frame] backend frame upload success (object storage)`);
875
+ return;
876
+ }
877
+ // 'disabled' → storage not configured server-side; fall through to inline.
878
+ }
879
+
880
+ // Legacy inline path: base64 in JSON body.
881
+ const frames = batch.map(b => ({ ...this._frameMeta(b), imageData: b.imageData }));
882
+ const framesEndpoint = this.config.clientKey
883
+ ? ENDPOINTS.INGESTION_FRAMES(sessionId)
884
+ : `/replay/sessions/${sessionId}/frames`;
885
+ await this._post(framesEndpoint, { frames });
886
+ logger.info(`[replay.sdk.frame] backend frame upload success`);
887
+ }
888
+
889
+ // ─── Cross-kill frame recovery ──────────────────────────────────────
890
+ //
891
+ // Frames buffer in-memory (pendingFrames) and only reach the backend on flush.
892
+ // A process kill (swipe-away, OOM) between captures loses the last frames the
893
+ // user saw — the iOS/Android background flush may be suspended before its POST
894
+ // resolves. To close that gap we snapshot the unflushed buffer to the durable
895
+ // KV store on background (survives kill), then re-upload it on the NEXT launch
896
+ // linked to the PRIOR session id. Best-effort and never throws.
897
+
898
+ /**
899
+ * Snapshot the current unflushed frame buffer to durable storage so it survives
900
+ * a process kill. Called on APP_BACKGROUND before the (possibly-suspended)
901
+ * network flush. Synchronous mirror write — reaches disk on the native store's
902
+ * next coalesced flush. No-op if recovery storage is absent or nothing pending.
903
+ */
904
+ persistPendingFrames(): void {
905
+ if (!this._frameStore || this.destroyed || !this.currentSessionId) return;
906
+ if (this.pendingFrames.length === 0) return;
907
+ try {
908
+ const items = this.pendingFrames.slice(-BackendSessionAdapter.MAX_PERSIST_FRAMES);
909
+ this._frameStore.set(
910
+ BackendSessionAdapter.PENDING_FRAMES_KEY,
911
+ JSON.stringify({ sessionId: this.currentSessionId, items }),
912
+ );
913
+ } catch {
914
+ // Serialization/storage failure must never break backgrounding.
915
+ }
916
+ }
917
+
918
+ /** Drop the persisted frame snapshot (after successful delivery). Never throws. */
919
+ private _clearPersistedFrames(): void {
920
+ if (!this._frameStore) return;
921
+ try {
922
+ this._frameStore.delete(BackendSessionAdapter.PENDING_FRAMES_KEY);
923
+ } catch {
924
+ /* non-fatal */
925
+ }
926
+ }
927
+
928
+ /**
929
+ * On cold launch: if a prior run left an unflushed frame snapshot, re-upload it
930
+ * linked to that PRIOR session, then clear it. Runs independently of the new
931
+ * session (uses the stored id + a direct POST, bypassing the row-ready gate —
932
+ * the prior session row already exists server-side). Best-effort; on transient
933
+ * failure the snapshot is kept for the next launch.
934
+ */
935
+ async recoverPersistedFrames(): Promise<void> {
936
+ if (!this._frameStore) return;
937
+ let raw: string | undefined;
938
+ try {
939
+ raw = this._frameStore.get(BackendSessionAdapter.PENDING_FRAMES_KEY);
940
+ } catch {
941
+ return;
942
+ }
943
+ if (!raw) return;
944
+
945
+ let parsed: { sessionId?: string; items?: Array<{ frame: ReplayFrame; imageData: string }> };
946
+ try {
947
+ parsed = JSON.parse(raw);
948
+ } catch {
949
+ // Corrupt snapshot — discard so it can't wedge every launch.
950
+ this._clearPersistedFrames();
951
+ return;
952
+ }
953
+
954
+ const sessionId = parsed.sessionId;
955
+ const items = parsed.items;
956
+ if (!sessionId || !Array.isArray(items) || items.length === 0) {
957
+ this._clearPersistedFrames();
958
+ return;
959
+ }
960
+
961
+ try {
962
+ logger.info(`[replay.sdk.frame] recovering ${items.length} frame(s) for prior session ${sessionId}`);
963
+ await this._postFrameBatch(sessionId, items);
964
+ this._clearPersistedFrames();
965
+ } catch (err) {
966
+ if (BackendSessionAdapter._isPermanentHttpError(err)) {
967
+ // Server rejected permanently (e.g. session gone) — don't retry forever.
968
+ this._clearPersistedFrames();
969
+ return;
970
+ }
971
+ // Transient — keep the snapshot for the next launch.
972
+ logger.warn(`[replay.sdk.frame] prior-session frame recovery deferred (transient)`);
973
+ }
974
+ }
975
+
976
+ /**
977
+ * Upload a batch via object storage. Returns 'sent' on success, 'disabled' if
978
+ * the backend reports storage is not configured (caller falls back to inline).
979
+ * Throws on transient error so the caller re-queues the batch.
980
+ */
981
+ private async _uploadFramesViaStorage(
982
+ sessionId: string,
983
+ batch: Array<{ frame: ReplayFrame; imageData: string }>,
984
+ ): Promise<'sent' | 'disabled'> {
985
+ const presignReq = batch.map(b => {
986
+ const m = this._frameMeta(b);
987
+ return { frameId: m.frameId, contentType: m.contentType, format: m.format };
988
+ });
989
+ const resp = await this._postReturning<{ enabled: boolean; frames: Array<{ frameId: string; uploadUrl: string; storageKey: string; bucket: string; contentType: string }> }>(
990
+ ENDPOINTS.INGESTION_FRAMES_PRESIGN(sessionId),
991
+ { frames: presignReq },
992
+ );
993
+
994
+ if (!resp || resp.enabled === false) {
995
+ // Latch off for the rest of the session so we don't presign every batch.
996
+ this.objectStorageActive = false;
997
+ return 'disabled';
998
+ }
999
+
1000
+ const byFrameId = new Map(resp.frames.map(p => [p.frameId, p]));
1001
+
1002
+ // Upload bytes directly to storage (backend never sees image bytes here).
1003
+ await Promise.all(batch.map(async b => {
1004
+ const p = byFrameId.get(b.frame.frameId);
1005
+ if (!p) throw new Error(`No presign URL for frame ${b.frame.frameId}`);
1006
+ await this._putBytes(p.uploadUrl, b.imageData, p.contentType);
1007
+ }));
1008
+
1009
+ // Persist key-only metadata (no base64 in the body).
1010
+ const frames = batch.map(b => {
1011
+ const p = byFrameId.get(b.frame.frameId)!;
1012
+ return { ...this._frameMeta(b), storageKey: p.storageKey, contentType: p.contentType };
1013
+ });
1014
+ await this._post(ENDPOINTS.INGESTION_FRAMES(sessionId), { frames });
1015
+ return 'sent';
1016
+ }
1017
+
1018
+ private async _flushEvents(): Promise<void> {
1019
+ if (this.pendingEvents.length === 0 || !this.currentSessionId) return;
1020
+
1021
+ const batch = this.pendingEvents.splice(0, 20);
1022
+ const events = batch.map(e => this._leanEvent(e, e.sessionId));
1023
+
1024
+ try {
1025
+ logger.info(`[replay.sdk.event] backend event upload started`, { count: batch.length });
1026
+ // Durable native outbox owns delivery when active (no duplicate JS POST).
1027
+ // The native enqueue is NOT gated on row-readiness: it writes to disk and its
1028
+ // uploader handles ordering/retry, so it must accept data even while offline.
1029
+ if (await this._enqueueNative('events', events)) return;
1030
+ // §11: JS-direct POST only after the session_start row exists; else re-buffer.
1031
+ if (!this._sessionRowReady()) { this.pendingEvents.unshift(...batch); return; }
1032
+ const eventsEndpoint = this.config.clientKey
1033
+ ? ENDPOINTS.INGESTION_EVENTS(this.currentSessionId)
1034
+ : `/replay/sessions/${this.currentSessionId}/events`;
1035
+ await this._post(
1036
+ eventsEndpoint,
1037
+ { events },
1038
+ );
1039
+ logger.info(`[replay.sdk.event] backend event upload success`);
1040
+ logger.debug(`[BackendSessionAdapter] Flushed ${batch.length} event(s)`);
1041
+ } catch (err) {
1042
+ if (BackendSessionAdapter._isPermanentHttpError(err)) return;
1043
+ logger.warn(`[replay.sdk.error] backend event upload failure`, { count: batch.length });
1044
+ this.pendingEvents.unshift(...batch);
1045
+ }
1046
+ }
1047
+
1048
+ private async _flushNetwork(): Promise<void> {
1049
+ if (this.pendingNetworkRequests.length === 0 || !this.currentSessionId || !this.config.clientKey) return;
1050
+ const batch = this.pendingNetworkRequests.splice(0, 50);
1051
+ try {
1052
+ if (await this._enqueueNative('network', batch)) return;
1053
+ if (!this._sessionRowReady()) { this.pendingNetworkRequests.unshift(...batch); return; }
1054
+ await this._post(ENDPOINTS.INGESTION_NETWORK(this.currentSessionId), { requests: batch });
1055
+ } catch (err) {
1056
+ if (!BackendSessionAdapter._isPermanentHttpError(err)) this.pendingNetworkRequests.unshift(...batch);
1057
+ }
1058
+ }
1059
+
1060
+ private async _flushErrors(): Promise<void> {
1061
+ if (this.pendingErrors.length === 0 || !this.currentSessionId || !this.config.clientKey) return;
1062
+ const batch = this.pendingErrors.splice(0, 20);
1063
+ try {
1064
+ if (await this._enqueueNative('errors', batch)) return;
1065
+ if (!this._sessionRowReady()) { this.pendingErrors.unshift(...batch); return; }
1066
+ await this._post(ENDPOINTS.INGESTION_ERRORS(this.currentSessionId), { errors: batch });
1067
+ } catch (err) {
1068
+ if (!BackendSessionAdapter._isPermanentHttpError(err)) this.pendingErrors.unshift(...batch);
1069
+ }
1070
+ }
1071
+
1072
+ private async _flushPerformance(): Promise<void> {
1073
+ if (this.pendingPerformanceMetrics.length === 0 || !this.currentSessionId || !this.config.clientKey) return;
1074
+ const batch = this.pendingPerformanceMetrics.splice(0, 50);
1075
+ try {
1076
+ if (await this._enqueueNative('performance', batch)) return;
1077
+ if (!this._sessionRowReady()) { this.pendingPerformanceMetrics.unshift(...batch); return; }
1078
+ await this._post(ENDPOINTS.INGESTION_PERFORMANCE(this.currentSessionId), { metrics: batch });
1079
+ } catch (err) {
1080
+ if (!BackendSessionAdapter._isPermanentHttpError(err)) this.pendingPerformanceMetrics.unshift(...batch);
1081
+ }
1082
+ }
1083
+
1084
+ private async _flushLogs(): Promise<void> {
1085
+ if (this.pendingLogs.length === 0 || !this.currentSessionId || !this.config.clientKey) return;
1086
+ const batch = this.pendingLogs.splice(0, BackendSessionAdapter.LOGS_FLUSH_MAX);
1087
+ try {
1088
+ if (await this._enqueueNative('logs', batch as unknown as Array<Record<string, unknown>>)) return;
1089
+ if (!this._sessionRowReady()) { this.pendingLogs.unshift(...batch); return; }
1090
+ await this._post(ENDPOINTS.INGESTION_LOGS(this.currentSessionId), { logs: batch });
1091
+ } catch (err) {
1092
+ if (!BackendSessionAdapter._isPermanentHttpError(err)) this.pendingLogs.unshift(...batch);
1093
+ }
1094
+ }
1095
+
1096
+ // ─── Internal: Timer ────────────────────────────────────────────────
1097
+
1098
+ private _startFlushTimer(): void {
1099
+ this._stopFlushTimer();
1100
+ this.flushTimer = setInterval(() => {
1101
+ this._flushFrames().catch(() => { });
1102
+ this._flushEvents().catch(() => { });
1103
+ this._flushNetwork().catch(() => { });
1104
+ this._flushErrors().catch(() => { });
1105
+ this._flushPerformance().catch(() => { });
1106
+ this._flushLogs().catch(() => { });
1107
+ this._triggerNativeFlush();
1108
+ }, this.config.flushIntervalMs);
1109
+ }
1110
+
1111
+ private _stopFlushTimer(): void {
1112
+ if (this.flushTimer) {
1113
+ clearInterval(this.flushTimer);
1114
+ this.flushTimer = null;
1115
+ }
1116
+ }
1117
+
1118
+ // ─── Internal: HTTP ─────────────────────────────────────────────────
1119
+
1120
+ // A 4xx (except 408 Request Timeout / 429 Too Many Requests) is permanent:
1121
+ // the same payload will never succeed, so requeuing it retries forever and
1122
+ // floods the logs (e.g. a rejected clientKey → HTTP 403 on every flush tick).
1123
+ // Drop the batch on these; keep retrying 5xx / timeouts / network errors.
1124
+ private static _isPermanentHttpError(err: unknown): boolean {
1125
+ const status = (err as { status?: number })?.status;
1126
+ return typeof status === 'number' && status >= 400 && status < 500 && status !== 408 && status !== 429;
1127
+ }
1128
+
1129
+ private async _post(path: string, body: unknown): Promise<void> {
1130
+ const url = `${this.config.endpoint}${path}`;
1131
+
1132
+ try {
1133
+ const controller = new AbortController();
1134
+ const timeout = setTimeout(() => controller.abort(), this.config.timeoutMs);
1135
+
1136
+ try {
1137
+ const headers: Record<string, string> = { 'Content-Type': 'application/json' };
1138
+ if (this.config.clientKey) {
1139
+ headers['x-scalebun-client-key'] = this.config.clientKey;
1140
+ }
1141
+ const response = await fetch(url, {
1142
+ method: 'POST',
1143
+ headers,
1144
+ body: JSON.stringify(body),
1145
+ signal: controller.signal,
1146
+ });
1147
+
1148
+ if (!response.ok) {
1149
+ logger.warn(`[BackendSessionAdapter] HTTP ${response.status} from ${path}`);
1150
+ const httpErr = new Error(`HTTP ${response.status}`) as Error & { status?: number };
1151
+ httpErr.status = response.status;
1152
+ throw httpErr;
1153
+ }
1154
+ } finally {
1155
+ clearTimeout(timeout);
1156
+ }
1157
+ } catch (err: any) {
1158
+ if (err?.name === 'AbortError') {
1159
+ logger.warn(`[BackendSessionAdapter] Timeout on ${path}`);
1160
+ } else {
1161
+ logger.warn(`[BackendSessionAdapter] Failed ${path}: ${err?.message}`);
1162
+ }
1163
+ throw err;
1164
+ }
1165
+ }
1166
+
1167
+ /**
1168
+ * POST that parses and returns the JSON response body. Mirrors _post's headers
1169
+ * and timeout handling; used by the object-storage presign request, which needs
1170
+ * the returned upload URLs (the void _post discards the body).
1171
+ */
1172
+ private async _postReturning<T>(path: string, body: unknown): Promise<T> {
1173
+ const url = `${this.config.endpoint}${path}`;
1174
+
1175
+ const controller = new AbortController();
1176
+ const timeout = setTimeout(() => controller.abort(), this.config.timeoutMs);
1177
+ try {
1178
+ const headers: Record<string, string> = { 'Content-Type': 'application/json' };
1179
+ if (this.config.clientKey) {
1180
+ headers['x-scalebun-client-key'] = this.config.clientKey;
1181
+ }
1182
+ const response = await fetch(url, {
1183
+ method: 'POST',
1184
+ headers,
1185
+ body: JSON.stringify(body),
1186
+ signal: controller.signal,
1187
+ });
1188
+ if (!response.ok) {
1189
+ logger.warn(`[BackendSessionAdapter] HTTP ${response.status} from ${path}`);
1190
+ const httpErr = new Error(`HTTP ${response.status}`) as Error & { status?: number };
1191
+ httpErr.status = response.status;
1192
+ throw httpErr;
1193
+ }
1194
+ return (await response.json()) as T;
1195
+ } finally {
1196
+ clearTimeout(timeout);
1197
+ }
1198
+ }
1199
+
1200
+ /**
1201
+ * PUT raw image bytes directly to a presigned storage URL. Decodes the base64
1202
+ * frame payload to a binary Blob so the wire body is bytes, not a base64 string.
1203
+ * No client key header — the presigned URL carries its own auth.
1204
+ */
1205
+ private async _putBytes(uploadUrl: string, base64: string, contentType: string): Promise<void> {
1206
+ // RN-safe base64→binary: decode to a Uint8Array and send that as the body.
1207
+ // The `fetch('data:…').blob()` round-trip fails under the new architecture
1208
+ // ("Network request failed"); RN's XHR sends a typed array as real binary.
1209
+ const bytes = base64ToBytes(this._stripDataUri(base64));
1210
+
1211
+ const controller = new AbortController();
1212
+ const timeout = setTimeout(() => controller.abort(), this.config.timeoutMs);
1213
+ try {
1214
+ const response = await fetch(uploadUrl, {
1215
+ method: 'PUT',
1216
+ headers: { 'Content-Type': contentType },
1217
+ body: bytes,
1218
+ signal: controller.signal,
1219
+ });
1220
+ if (!response.ok) {
1221
+ throw new Error(`HTTP ${response.status}`);
1222
+ }
1223
+ } finally {
1224
+ clearTimeout(timeout);
1225
+ }
1226
+ }
1227
+
1228
+ /** Strip a leading `data:<mime>;base64,` prefix if the native layer included one. */
1229
+ private _stripDataUri(s: string): string {
1230
+ const comma = s.indexOf(',');
1231
+ return s.startsWith('data:') && comma !== -1 ? s.slice(comma + 1) : s;
1232
+ }
1233
+ }