@scalebun/react-native 1.0.3 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/android/src/main/java/com/scalebun/core/crash/CrashStorage.kt +115 -1
- package/android/src/main/java/com/scalebun/core/crash/NativeCrashHandler.kt +14 -0
- package/android/src/main/java/com/scalebun/replaysdk/ReplaySdkModule.kt +25 -9
- package/android/src/main/java/com/scalebun/replaysdk/voice/VoiceTranscriber.kt +68 -2
- package/android/src/main/java/com/scalebun/rn/crash/ScaleBunCrashModule.kt +66 -2
- package/android/src/main/java/com/scalebun/rn/ota/SlotManager.kt +70 -4
- package/ios/Crash/ScaleBunCrashBridge.mm +6 -0
- package/ios/Crash/ScaleBunCrashHandler.swift +14 -1
- package/ios/Crash/ScaleBunCrashModule.swift +14 -0
- package/ios/Crash/ScaleBunCrashSignalBridge.h +32 -1
- package/ios/Crash/ScaleBunCrashSignalBridge.m +172 -7
- package/ios/Crash/ScaleBunCrashSignalStress.c +137 -0
- package/ios/Crash/ScaleBunCrashStorage.swift +75 -0
- package/lib/commonjs/analytics/EventTracker.js +30 -2
- package/lib/commonjs/analytics/EventTracker.js.map +1 -1
- package/lib/commonjs/bootstrap/SDKBootstrapper.js +31 -23
- package/lib/commonjs/bootstrap/SDKBootstrapper.js.map +1 -1
- package/lib/commonjs/compat/codepush.js +78 -15
- package/lib/commonjs/compat/codepush.js.map +1 -1
- package/lib/commonjs/core/config/schema.js +26 -5
- package/lib/commonjs/core/config/schema.js.map +1 -1
- package/lib/commonjs/core/constants/endpoints.js +9 -6
- package/lib/commonjs/core/constants/endpoints.js.map +1 -1
- package/lib/commonjs/core/context/device.js +130 -0
- package/lib/commonjs/core/context/device.js.map +1 -1
- package/lib/commonjs/debug/replayWiring.js +2 -1
- package/lib/commonjs/debug/replayWiring.js.map +1 -1
- package/lib/commonjs/features/bugreport/BugReportFeature.js +112 -0
- package/lib/commonjs/features/bugreport/BugReportFeature.js.map +1 -0
- package/lib/commonjs/features/bugreport/buildPayload.js +97 -0
- package/lib/commonjs/features/bugreport/buildPayload.js.map +1 -0
- package/lib/commonjs/features/crash/CrashReporter.js +25 -1
- package/lib/commonjs/features/crash/CrashReporter.js.map +1 -1
- package/lib/commonjs/features/crash/capture.js +27 -9
- package/lib/commonjs/features/crash/capture.js.map +1 -1
- package/lib/commonjs/features/crash/nativeCrashBridge.js +163 -28
- package/lib/commonjs/features/crash/nativeCrashBridge.js.map +1 -1
- package/lib/commonjs/features/engage/EngagePromptProvider.js +36 -2
- package/lib/commonjs/features/engage/EngagePromptProvider.js.map +1 -1
- package/lib/commonjs/features/engage/EngagePromptView.js +47 -14
- package/lib/commonjs/features/engage/EngagePromptView.js.map +1 -1
- package/lib/commonjs/features/engage/engageTriggerEngine.js +10 -0
- package/lib/commonjs/features/engage/engageTriggerEngine.js.map +1 -1
- package/lib/commonjs/features/engage/engageTypes.js.map +1 -1
- package/lib/commonjs/features/journey/ScaleBunDebugRoot.js +2 -1
- package/lib/commonjs/features/journey/ScaleBunDebugRoot.js.map +1 -1
- package/lib/commonjs/features/ota/OtaOrchestrator.js +72 -5
- package/lib/commonjs/features/ota/OtaOrchestrator.js.map +1 -1
- package/lib/commonjs/features/ota/deviceAttributes.js +48 -0
- package/lib/commonjs/features/ota/deviceAttributes.js.map +1 -0
- package/lib/commonjs/features/ota/geoCountry.js +93 -0
- package/lib/commonjs/features/ota/geoCountry.js.map +1 -0
- package/lib/commonjs/features/ota/useOtaUpdate.js +4 -1
- package/lib/commonjs/features/ota/useOtaUpdate.js.map +1 -1
- package/lib/commonjs/features/performance/PerformanceFeature.js +23 -9
- package/lib/commonjs/features/performance/PerformanceFeature.js.map +1 -1
- package/lib/commonjs/features/performance/collectors/FrameMetricsCollector.js +69 -9
- package/lib/commonjs/features/performance/collectors/FrameMetricsCollector.js.map +1 -1
- package/lib/commonjs/features/performance/transport/PerformanceTransport.js +25 -0
- package/lib/commonjs/features/performance/transport/PerformanceTransport.js.map +1 -1
- package/lib/commonjs/features/session/BackendSessionAdapter.js +128 -11
- package/lib/commonjs/features/session/BackendSessionAdapter.js.map +1 -1
- package/lib/commonjs/features/session/JourneyEventPipeline.js +1 -0
- package/lib/commonjs/features/session/JourneyEventPipeline.js.map +1 -1
- package/lib/commonjs/features/session/ReplayCaptureManager.js +46 -0
- package/lib/commonjs/features/session/ReplayCaptureManager.js.map +1 -1
- package/lib/commonjs/features/session/SessionManager.js +42 -12
- package/lib/commonjs/features/session/SessionManager.js.map +1 -1
- package/lib/commonjs/features/session/nativeCapture.js +4 -4
- package/lib/commonjs/features/session/nativeCapture.js.map +1 -1
- package/lib/commonjs/features/session/outboxFrameCapture.js +3 -2
- package/lib/commonjs/features/session/outboxFrameCapture.js.map +1 -1
- package/lib/commonjs/features/session/sessionTypes.js.map +1 -1
- package/lib/commonjs/index.js +13 -0
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/public/ScaleBunFacade.js +199 -2
- package/lib/commonjs/public/ScaleBunFacade.js.map +1 -1
- package/lib/commonjs/specs/NativeScaleBunCrash.js.map +1 -1
- package/lib/module/analytics/EventTracker.js +29 -1
- package/lib/module/analytics/EventTracker.js.map +1 -1
- package/lib/module/bootstrap/SDKBootstrapper.js +29 -21
- package/lib/module/bootstrap/SDKBootstrapper.js.map +1 -1
- package/lib/module/compat/codepush.js +77 -14
- package/lib/module/compat/codepush.js.map +1 -1
- package/lib/module/core/config/schema.js +26 -5
- package/lib/module/core/config/schema.js.map +1 -1
- package/lib/module/core/constants/endpoints.js +9 -6
- package/lib/module/core/constants/endpoints.js.map +1 -1
- package/lib/module/core/context/device.js +119 -0
- package/lib/module/core/context/device.js.map +1 -1
- package/lib/module/debug/replayWiring.js +2 -1
- package/lib/module/debug/replayWiring.js.map +1 -1
- package/lib/module/features/bugreport/BugReportFeature.js +105 -0
- package/lib/module/features/bugreport/BugReportFeature.js.map +1 -0
- package/lib/module/features/bugreport/buildPayload.js +91 -0
- package/lib/module/features/bugreport/buildPayload.js.map +1 -0
- package/lib/module/features/crash/CrashReporter.js +25 -1
- package/lib/module/features/crash/CrashReporter.js.map +1 -1
- package/lib/module/features/crash/capture.js +28 -9
- package/lib/module/features/crash/capture.js.map +1 -1
- package/lib/module/features/crash/nativeCrashBridge.js +161 -28
- package/lib/module/features/crash/nativeCrashBridge.js.map +1 -1
- package/lib/module/features/engage/EngagePromptProvider.js +36 -2
- package/lib/module/features/engage/EngagePromptProvider.js.map +1 -1
- package/lib/module/features/engage/EngagePromptView.js +47 -14
- package/lib/module/features/engage/EngagePromptView.js.map +1 -1
- package/lib/module/features/engage/engageTriggerEngine.js +10 -0
- package/lib/module/features/engage/engageTriggerEngine.js.map +1 -1
- package/lib/module/features/engage/engageTypes.js.map +1 -1
- package/lib/module/features/journey/ScaleBunDebugRoot.js +2 -1
- package/lib/module/features/journey/ScaleBunDebugRoot.js.map +1 -1
- package/lib/module/features/ota/OtaOrchestrator.js +72 -5
- package/lib/module/features/ota/OtaOrchestrator.js.map +1 -1
- package/lib/module/features/ota/deviceAttributes.js +43 -0
- package/lib/module/features/ota/deviceAttributes.js.map +1 -0
- package/lib/module/features/ota/geoCountry.js +86 -0
- package/lib/module/features/ota/geoCountry.js.map +1 -0
- package/lib/module/features/ota/useOtaUpdate.js +4 -1
- package/lib/module/features/ota/useOtaUpdate.js.map +1 -1
- package/lib/module/features/performance/PerformanceFeature.js +23 -9
- package/lib/module/features/performance/PerformanceFeature.js.map +1 -1
- package/lib/module/features/performance/collectors/FrameMetricsCollector.js +70 -10
- package/lib/module/features/performance/collectors/FrameMetricsCollector.js.map +1 -1
- package/lib/module/features/performance/transport/PerformanceTransport.js +25 -0
- package/lib/module/features/performance/transport/PerformanceTransport.js.map +1 -1
- package/lib/module/features/session/BackendSessionAdapter.js +128 -11
- package/lib/module/features/session/BackendSessionAdapter.js.map +1 -1
- package/lib/module/features/session/JourneyEventPipeline.js +1 -0
- package/lib/module/features/session/JourneyEventPipeline.js.map +1 -1
- package/lib/module/features/session/ReplayCaptureManager.js +46 -0
- package/lib/module/features/session/ReplayCaptureManager.js.map +1 -1
- package/lib/module/features/session/SessionManager.js +42 -12
- package/lib/module/features/session/SessionManager.js.map +1 -1
- package/lib/module/features/session/nativeCapture.js +4 -5
- package/lib/module/features/session/nativeCapture.js.map +1 -1
- package/lib/module/features/session/outboxFrameCapture.js +3 -2
- package/lib/module/features/session/outboxFrameCapture.js.map +1 -1
- package/lib/module/features/session/sessionTypes.js.map +1 -1
- package/lib/module/index.js +4 -1
- package/lib/module/index.js.map +1 -1
- package/lib/module/public/ScaleBunFacade.js +199 -2
- package/lib/module/public/ScaleBunFacade.js.map +1 -1
- package/lib/module/specs/NativeScaleBunCrash.js.map +1 -1
- package/lib/typescript/analytics/EventTracker.d.ts +20 -0
- package/lib/typescript/analytics/EventTracker.d.ts.map +1 -1
- package/lib/typescript/bootstrap/SDKBootstrapper.d.ts.map +1 -1
- package/lib/typescript/compat/codepush.d.ts +27 -4
- package/lib/typescript/compat/codepush.d.ts.map +1 -1
- package/lib/typescript/core/config/schema.d.ts +4 -1
- package/lib/typescript/core/config/schema.d.ts.map +1 -1
- package/lib/typescript/core/constants/endpoints.d.ts +9 -6
- package/lib/typescript/core/constants/endpoints.d.ts.map +1 -1
- package/lib/typescript/core/context/device.d.ts +46 -0
- package/lib/typescript/core/context/device.d.ts.map +1 -1
- package/lib/typescript/debug/replayWiring.d.ts.map +1 -1
- package/lib/typescript/features/bugreport/BugReportFeature.d.ts +59 -0
- package/lib/typescript/features/bugreport/BugReportFeature.d.ts.map +1 -0
- package/lib/typescript/features/bugreport/buildPayload.d.ts +51 -0
- package/lib/typescript/features/bugreport/buildPayload.d.ts.map +1 -0
- package/lib/typescript/features/crash/CrashReporter.d.ts +20 -1
- package/lib/typescript/features/crash/CrashReporter.d.ts.map +1 -1
- package/lib/typescript/features/crash/capture.d.ts +21 -2
- package/lib/typescript/features/crash/capture.d.ts.map +1 -1
- package/lib/typescript/features/crash/nativeCrashBridge.d.ts +16 -3
- package/lib/typescript/features/crash/nativeCrashBridge.d.ts.map +1 -1
- package/lib/typescript/features/engage/EngagePromptProvider.d.ts.map +1 -1
- package/lib/typescript/features/engage/EngagePromptView.d.ts.map +1 -1
- package/lib/typescript/features/engage/EngageTransport.d.ts +1 -1
- package/lib/typescript/features/engage/EngageTransport.d.ts.map +1 -1
- package/lib/typescript/features/engage/engageTriggerEngine.d.ts.map +1 -1
- package/lib/typescript/features/engage/engageTypes.d.ts +15 -0
- package/lib/typescript/features/engage/engageTypes.d.ts.map +1 -1
- package/lib/typescript/features/journey/ScaleBunDebugRoot.d.ts.map +1 -1
- package/lib/typescript/features/ota/OtaOrchestrator.d.ts +14 -2
- package/lib/typescript/features/ota/OtaOrchestrator.d.ts.map +1 -1
- package/lib/typescript/features/ota/deviceAttributes.d.ts +18 -0
- package/lib/typescript/features/ota/deviceAttributes.d.ts.map +1 -0
- package/lib/typescript/features/ota/geoCountry.d.ts +14 -0
- package/lib/typescript/features/ota/geoCountry.d.ts.map +1 -0
- package/lib/typescript/features/ota/useOtaUpdate.d.ts +20 -2
- package/lib/typescript/features/ota/useOtaUpdate.d.ts.map +1 -1
- package/lib/typescript/features/performance/PerformanceFeature.d.ts +0 -1
- package/lib/typescript/features/performance/PerformanceFeature.d.ts.map +1 -1
- package/lib/typescript/features/performance/collectors/FrameMetricsCollector.d.ts +33 -0
- package/lib/typescript/features/performance/collectors/FrameMetricsCollector.d.ts.map +1 -1
- package/lib/typescript/features/performance/transport/PerformanceTransport.d.ts.map +1 -1
- package/lib/typescript/features/session/BackendSessionAdapter.d.ts +42 -2
- package/lib/typescript/features/session/BackendSessionAdapter.d.ts.map +1 -1
- package/lib/typescript/features/session/JourneyEventPipeline.d.ts +2 -0
- package/lib/typescript/features/session/JourneyEventPipeline.d.ts.map +1 -1
- package/lib/typescript/features/session/ReplayCaptureManager.d.ts +38 -1
- package/lib/typescript/features/session/ReplayCaptureManager.d.ts.map +1 -1
- package/lib/typescript/features/session/SessionManager.d.ts.map +1 -1
- package/lib/typescript/features/session/nativeCapture.d.ts +2 -1
- package/lib/typescript/features/session/nativeCapture.d.ts.map +1 -1
- package/lib/typescript/features/session/outboxFrameCapture.d.ts.map +1 -1
- package/lib/typescript/features/session/sessionTypes.d.ts +20 -3
- package/lib/typescript/features/session/sessionTypes.d.ts.map +1 -1
- package/lib/typescript/index.d.ts +1 -0
- package/lib/typescript/index.d.ts.map +1 -1
- package/lib/typescript/public/ScaleBunFacade.d.ts +69 -0
- package/lib/typescript/public/ScaleBunFacade.d.ts.map +1 -1
- package/lib/typescript/public/types.d.ts +34 -8
- package/lib/typescript/public/types.d.ts.map +1 -1
- package/lib/typescript/specs/NativeScaleBunCrash.d.ts +14 -0
- package/lib/typescript/specs/NativeScaleBunCrash.d.ts.map +1 -1
- package/lib/typescript/vendor/protocol/index.d.ts +17 -17
- package/package.json +1 -1
- package/src/analytics/EventTracker.ts +28 -1
- package/src/bootstrap/SDKBootstrapper.ts +27 -23
- package/src/compat/codepush.ts +87 -16
- package/src/core/config/schema.ts +26 -5
- package/src/core/constants/endpoints.ts +9 -6
- package/src/core/context/device.ts +146 -0
- package/src/debug/replayWiring.ts +2 -1
- package/src/features/bugreport/BugReportFeature.ts +128 -0
- package/src/features/bugreport/buildPayload.ts +116 -0
- package/src/features/crash/CrashReporter.ts +40 -1
- package/src/features/crash/capture.ts +36 -9
- package/src/features/crash/nativeCrashBridge.ts +156 -22
- package/src/features/engage/EngagePromptProvider.tsx +48 -2
- package/src/features/engage/EngagePromptView.tsx +51 -15
- package/src/features/engage/EngageTransport.ts +1 -1
- package/src/features/engage/engageTriggerEngine.ts +15 -0
- package/src/features/engage/engageTypes.ts +15 -0
- package/src/features/journey/ScaleBunDebugRoot.tsx +2 -1
- package/src/features/ota/OtaOrchestrator.ts +84 -6
- package/src/features/ota/deviceAttributes.ts +46 -0
- package/src/features/ota/geoCountry.ts +85 -0
- package/src/features/ota/useOtaUpdate.ts +20 -2
- package/src/features/performance/PerformanceFeature.ts +22 -9
- package/src/features/performance/collectors/FrameMetricsCollector.ts +72 -10
- package/src/features/performance/transport/PerformanceTransport.ts +18 -0
- package/src/features/session/BackendSessionAdapter.ts +137 -10
- package/src/features/session/JourneyEventPipeline.ts +3 -0
- package/src/features/session/ReplayCaptureManager.ts +53 -1
- package/src/features/session/SessionManager.ts +46 -7
- package/src/features/session/nativeCapture.ts +3 -2
- package/src/features/session/outboxFrameCapture.ts +3 -2
- package/src/features/session/sessionTypes.ts +26 -3
- package/src/index.ts +4 -1
- package/src/public/ScaleBunFacade.ts +198 -2
- package/src/public/types.ts +35 -8
- package/src/specs/NativeScaleBunCrash.ts +16 -0
|
@@ -13,10 +13,14 @@ import { noThrow, safeAsync } from '../core/lifecycle/crashSafe';
|
|
|
13
13
|
import { logger } from '../core/logger/internalLogger';
|
|
14
14
|
import { createEnvelope } from '../pipeline/envelope/envelope';
|
|
15
15
|
import { generateEventId } from '../features/replay/core/ids/sessionId';
|
|
16
|
+
import { buildBugReportPayload } from '../features/bugreport/buildPayload';
|
|
17
|
+
import type { BugSubmitResult } from '../features/bugreport/BugReportFeature';
|
|
18
|
+
import { BugReportFeature } from '../features/bugreport/BugReportFeature';
|
|
16
19
|
import { PersistentQueue } from '../pipeline/queue/persistentQueue';
|
|
17
20
|
import { MemoryBackend, createStorageBackend } from '../storage/StorageBackend';
|
|
18
21
|
import { HttpClient } from '../transport/http/httpClient';
|
|
19
22
|
import { getDeviceId } from '../core/id/deviceId';
|
|
23
|
+
import { mergeDeviceContext } from '../core/context/device';
|
|
20
24
|
import { coreContainer } from '../core/di/container';
|
|
21
25
|
import { flushQueue } from '../pipeline/queue/flushQueue';
|
|
22
26
|
import {
|
|
@@ -247,6 +251,13 @@ class ScaleBunFacade {
|
|
|
247
251
|
// Continue — debug connection is independent of backend API
|
|
248
252
|
}
|
|
249
253
|
|
|
254
|
+
// OTA from init config. Without this the whole `ota` config block was
|
|
255
|
+
// inert: `otaOrchestrator.init()` was reachable only by importing the
|
|
256
|
+
// orchestrator directly, so an app that followed the documented
|
|
257
|
+
// `ota: { enabled: true }` path silently got no updates AND no
|
|
258
|
+
// signature enforcement (sync() gates on the flag init() sets).
|
|
259
|
+
this._maybeStartOta(rawConfig);
|
|
260
|
+
|
|
250
261
|
// Auto debug connection from init config — runs regardless of backend status
|
|
251
262
|
const debugConfig = (rawConfig?.desktopDebug ?? rawConfig?.debug) as DebugConnectionConfig | undefined;
|
|
252
263
|
if (debugConfig) {
|
|
@@ -260,6 +271,44 @@ class ScaleBunFacade {
|
|
|
260
271
|
}
|
|
261
272
|
}
|
|
262
273
|
|
|
274
|
+
/**
|
|
275
|
+
* Boot the OTA orchestrator when the init config asks for it.
|
|
276
|
+
*
|
|
277
|
+
* `publicSigningKey` is honoured here so signature enforcement is reachable
|
|
278
|
+
* from configuration alone. The SDK ships no ed25519 implementation, so a
|
|
279
|
+
* host that pins a key must also supply `ota.verifySignature`; pinning a key
|
|
280
|
+
* without a verifier is fail-CLOSED by design (signature.ts) — an update
|
|
281
|
+
* that cannot be verified is not installed. We say that out loud rather than
|
|
282
|
+
* letting the app discover it as a silent no-update condition.
|
|
283
|
+
*/
|
|
284
|
+
private _maybeStartOta(rawConfig: any): void {
|
|
285
|
+
const ota = rawConfig?.ota;
|
|
286
|
+
if (!ota?.enabled) return;
|
|
287
|
+
try {
|
|
288
|
+
// Required lazily: hosts that never enable OTA should not pay for the
|
|
289
|
+
// module (or touch the native spec) at import time.
|
|
290
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
291
|
+
const { otaOrchestrator } = require('../features/ota/OtaOrchestrator');
|
|
292
|
+
const publicKey = ota.publicSigningKey;
|
|
293
|
+
const verifier = ota.verifySignature;
|
|
294
|
+
if (publicKey && typeof verifier !== 'function') {
|
|
295
|
+
logger.warn(
|
|
296
|
+
'[ScaleBun] ota.publicSigningKey is set but ota.verifySignature is not a function. ' +
|
|
297
|
+
'Signature checking is fail-closed: updates will be REJECTED until a verifier is supplied.',
|
|
298
|
+
);
|
|
299
|
+
}
|
|
300
|
+
otaOrchestrator.init({
|
|
301
|
+
...(publicKey ? { signature: { publicKey, verifier } } : {}),
|
|
302
|
+
...(typeof ota.healthyTimeoutMs === 'number'
|
|
303
|
+
? { healthyTimeoutMs: ota.healthyTimeoutMs }
|
|
304
|
+
: {}),
|
|
305
|
+
});
|
|
306
|
+
logger.info('[ScaleBun] OTA enabled from init config.');
|
|
307
|
+
} catch (err: any) {
|
|
308
|
+
logger.warn(`[ScaleBun] OTA init failed: ${err?.message ?? err}`);
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
|
|
263
312
|
private _autoEnableDebug(debugConfig: DebugConnectionConfig): void {
|
|
264
313
|
try {
|
|
265
314
|
const dbgConfig = buildDebugConfigFromInitConfig(debugConfig);
|
|
@@ -278,7 +327,9 @@ class ScaleBunFacade {
|
|
|
278
327
|
const appId = rawConfig?.appId;
|
|
279
328
|
const enabled = rawConfig?.eventTracking !== false;
|
|
280
329
|
const clientKey = this._clientKey ?? rawConfig?.clientKey;
|
|
281
|
-
|
|
330
|
+
// apiBaseUrl is LOCKED — use only the bootstrapped value, never fall back to raw
|
|
331
|
+
// integrator input, so the event-tracker/SKAdNetwork lane can't be repointed either.
|
|
332
|
+
const apiBaseUrl = this._apiBaseUrl;
|
|
282
333
|
if (!enabled || !appId || !clientKey || !apiBaseUrl) {
|
|
283
334
|
if (enabled && !appId) {
|
|
284
335
|
logger.info('[ScaleBun] Envelope event tracking disabled — no appId in init config.');
|
|
@@ -307,7 +358,16 @@ class ScaleBunFacade {
|
|
|
307
358
|
automaticEventTracking:
|
|
308
359
|
rawConfig?.automaticEventTracking === true,
|
|
309
360
|
flushIntervalMs: rawConfig?.flushIntervalMs,
|
|
310
|
-
|
|
361
|
+
/**
|
|
362
|
+
* DETECTED, not configured.
|
|
363
|
+
*
|
|
364
|
+
* This was `rawConfig?.context` — whatever the app typed. Production carries
|
|
365
|
+
* `device_model: "android"` and `manufacturer: "android"` from a hand-written
|
|
366
|
+
* literal, while the replay lane was reading the real values off the native bridge
|
|
367
|
+
* the whole time. The SDK knows the device; the integrator is guessing at it.
|
|
368
|
+
* Everything outside the detected keys is still theirs.
|
|
369
|
+
*/
|
|
370
|
+
context: mergeDeviceContext(rawConfig?.context),
|
|
311
371
|
// Use the same foreground id as replay/journey capture. The
|
|
312
372
|
// callback is resolved per event because the session subsystem
|
|
313
373
|
// may start after this tracker is constructed.
|
|
@@ -597,6 +657,125 @@ class ScaleBunFacade {
|
|
|
597
657
|
return null;
|
|
598
658
|
}
|
|
599
659
|
|
|
660
|
+
// ─── Bug reports (F-BUG) ────────────────────────────────────────────
|
|
661
|
+
|
|
662
|
+
/**
|
|
663
|
+
* Thin feature object; the facade owns the HTTP, mirroring the web SDK split.
|
|
664
|
+
* Its only job here is raising the 'report' capture signal so replay flushes.
|
|
665
|
+
*/
|
|
666
|
+
private readonly _bugReport = new BugReportFeature();
|
|
667
|
+
|
|
668
|
+
/**
|
|
669
|
+
* Submit a bug report against the CURRENT session.
|
|
670
|
+
*
|
|
671
|
+
* Mirrors the web SDK's `reportBugDetailed` ordering, which is load-bearing rather than
|
|
672
|
+
* incidental:
|
|
673
|
+
*
|
|
674
|
+
* 1. resolve the session — a report with no session cannot be joined to its evidence
|
|
675
|
+
* 2. signal 'report' — replay flushes its buffer so the report has visual context
|
|
676
|
+
* 3. snapshot the anchor — BEFORE the POST. A flush asks the recorder to deliver pending
|
|
677
|
+
* bytes; it cannot retroactively manufacture a frame, so an absent
|
|
678
|
+
* coordinate must stay absent rather than becoming a misleading
|
|
679
|
+
* "start of session" link in the dashboard
|
|
680
|
+
* 4. build + POST — bounds enforced by buildBugReportPayload against the server DTO
|
|
681
|
+
*
|
|
682
|
+
* Returns the report id, or `{ e }` naming which branch failed — 'init' (SDK not configured)
|
|
683
|
+
* reads differently from 'send' (network), and that difference is what tells an integrator
|
|
684
|
+
* whether to check their setup or their connection. It never throws: this is called from a UI
|
|
685
|
+
* the host app renders, usually from a user gesture, and an exception escaping into a React
|
|
686
|
+
* Native render tree is a redbox shown to the customer's user over a report they were sending us.
|
|
687
|
+
*/
|
|
688
|
+
public async reportBugDetailed(input: {
|
|
689
|
+
message: string;
|
|
690
|
+
title?: string;
|
|
691
|
+
email?: string;
|
|
692
|
+
clientReportId?: string;
|
|
693
|
+
}): Promise<BugSubmitResult> {
|
|
694
|
+
if (!input || !input.message || input.message.trim().length === 0) {
|
|
695
|
+
logger.warn('[ScaleBun] reportBug: a message is required');
|
|
696
|
+
return { e: 'empty' };
|
|
697
|
+
}
|
|
698
|
+
if (!this._clientKey || !this._apiBaseUrl) {
|
|
699
|
+
logger.warn('[ScaleBun] reportBug: SDK is not configured (clientKey/apiBaseUrl)');
|
|
700
|
+
return { e: 'init' };
|
|
701
|
+
}
|
|
702
|
+
|
|
703
|
+
const sessionId = this.getActiveSessionId();
|
|
704
|
+
if (!sessionId) {
|
|
705
|
+
// No session means no row to attach to, and the ingestion route is session-scoped.
|
|
706
|
+
logger.warn('[ScaleBun] reportBug: no active session');
|
|
707
|
+
return { e: 'init' };
|
|
708
|
+
}
|
|
709
|
+
|
|
710
|
+
try {
|
|
711
|
+
// Flush replay into the session BEFORE reading the anchor below.
|
|
712
|
+
this._bugReport.signalReport();
|
|
713
|
+
|
|
714
|
+
const coord = this._replayCoord();
|
|
715
|
+
const payload = buildBugReportPayload(input, this._recentBreadcrumbs(), {
|
|
716
|
+
replayCoord: coord,
|
|
717
|
+
timestamp: Date.now(),
|
|
718
|
+
});
|
|
719
|
+
|
|
720
|
+
const res = await fetch(
|
|
721
|
+
`${this._apiBaseUrl}/ingestion/sessions/${sessionId}/bug-reports`,
|
|
722
|
+
{
|
|
723
|
+
method: 'POST',
|
|
724
|
+
headers: {
|
|
725
|
+
'Content-Type': 'application/json',
|
|
726
|
+
'x-scalebun-client-key': this._clientKey,
|
|
727
|
+
},
|
|
728
|
+
body: JSON.stringify(payload),
|
|
729
|
+
},
|
|
730
|
+
);
|
|
731
|
+
if (!res.ok) {
|
|
732
|
+
logger.warn('[ScaleBun] reportBug: server rejected the report', res.status);
|
|
733
|
+
return { e: 'send' };
|
|
734
|
+
}
|
|
735
|
+
const body = await res.json().catch(() => null);
|
|
736
|
+
return body?.id ?? { e: 'send' };
|
|
737
|
+
} catch (err: any) {
|
|
738
|
+
logger.warn('[ScaleBun] reportBug failed:', err?.message);
|
|
739
|
+
return { e: 'send' };
|
|
740
|
+
}
|
|
741
|
+
}
|
|
742
|
+
|
|
743
|
+
/**
|
|
744
|
+
* The replay coordinate at submit time, or null.
|
|
745
|
+
*
|
|
746
|
+
* Deliberately returns null rather than a zeroed coordinate when replay is disabled, paused, or
|
|
747
|
+
* has not produced a frame yet — see the anchor note on reportBug.
|
|
748
|
+
*/
|
|
749
|
+
/**
|
|
750
|
+
* The replay coordinate at submit time.
|
|
751
|
+
*
|
|
752
|
+
* ALWAYS null today, deliberately and visibly.
|
|
753
|
+
*
|
|
754
|
+
* The web SDK reads this from its recorder, but the RN replay subsystem exposes no sequence or
|
|
755
|
+
* segment accessor on its public API (features/replay/public/api.ts) -- there is currently no
|
|
756
|
+
* supported way to ask it where playback is. Probing for it through an `any` cast would compile,
|
|
757
|
+
* miss, and leave every report anchor-less while looking wired: the same defect as the existing
|
|
758
|
+
* reportBug(), which emits an analytics event and looks like it files a report.
|
|
759
|
+
*
|
|
760
|
+
* Returning null keeps the payload HONEST -- buildBugReportPayload omits replaySeq entirely, so
|
|
761
|
+
* the dashboard shows no anchor rather than a false one pointing at the start of the session.
|
|
762
|
+
* To finish this: expose the current seq + segment id from the replay recorder, then read them
|
|
763
|
+
* here. The payload builder and its contract tests already handle a real coordinate, including
|
|
764
|
+
* a genuine seq of 0.
|
|
765
|
+
*/
|
|
766
|
+
private _replayCoord(): { seq?: number | null; segmentId?: string | null } | null {
|
|
767
|
+
return null;
|
|
768
|
+
}
|
|
769
|
+
/** Recent console breadcrumbs for quick triage. The full set already travels with the session. */
|
|
770
|
+
private _recentBreadcrumbs(): readonly unknown[] {
|
|
771
|
+
try {
|
|
772
|
+
const f = (this as any)._loggerFeature ?? (this as any)._consoleFeature;
|
|
773
|
+
return f?.getRecent?.() ?? [];
|
|
774
|
+
} catch {
|
|
775
|
+
return [];
|
|
776
|
+
}
|
|
777
|
+
}
|
|
778
|
+
|
|
600
779
|
// ─── Engage ─────────────────────────────────────────────────────────
|
|
601
780
|
|
|
602
781
|
/**
|
|
@@ -1131,6 +1310,23 @@ class ScaleBunFacade {
|
|
|
1131
1310
|
|
|
1132
1311
|
/** Report a bug (convenience wrapper over track) */
|
|
1133
1312
|
public reportBug(description: string, metadata?: Record<string, unknown>) {
|
|
1313
|
+
// D11: this used to be ONLY `track('$bug_report')` — an analytics event
|
|
1314
|
+
// with zero consumers (no mapper, no handler, no BugReport row), so
|
|
1315
|
+
// /diagnose/bug-reports stayed empty forever for RN apps while the web
|
|
1316
|
+
// SDK used the real ingest. Route to the same endpoint the web SDK
|
|
1317
|
+
// uses; the analytics event is kept as a breadcrumb, not the delivery.
|
|
1318
|
+
try {
|
|
1319
|
+
const transport = SessionManager.getExistingInstance()?.getBackendTransport();
|
|
1320
|
+
transport?.submitBugReport({
|
|
1321
|
+
message: description,
|
|
1322
|
+
title:
|
|
1323
|
+
typeof metadata?.title === 'string' ? (metadata.title as string) : undefined,
|
|
1324
|
+
email:
|
|
1325
|
+
typeof metadata?.email === 'string' ? (metadata.email as string) : undefined,
|
|
1326
|
+
});
|
|
1327
|
+
} catch {
|
|
1328
|
+
/* delivery is best-effort; the track below still records intent */
|
|
1329
|
+
}
|
|
1134
1330
|
return this.track('$bug_report', { description, ...metadata });
|
|
1135
1331
|
}
|
|
1136
1332
|
|
package/src/public/types.ts
CHANGED
|
@@ -78,14 +78,28 @@ export interface ScaleBunInitConfig {
|
|
|
78
78
|
/** Publishable API key from dashboard */
|
|
79
79
|
publishableKey: string;
|
|
80
80
|
/**
|
|
81
|
-
*
|
|
82
|
-
*
|
|
81
|
+
* @deprecated The endpoint is LOCKED to the ScaleBun cloud. Any value passed here is accepted
|
|
82
|
+
* (for backward compatibility) but ignored — the bootstrapper always uses the fixed
|
|
83
|
+
* `DEFAULT_API_BASE_URL`. To target a different backend, change that constant at build time.
|
|
83
84
|
*/
|
|
84
85
|
apiBaseUrl?: string;
|
|
85
86
|
/** @deprecated Use desktopDebug instead */
|
|
86
87
|
debug?: boolean;
|
|
87
|
-
/** Enable session replay capture. Default: true */
|
|
88
|
+
/** Enable session replay capture (feature on/off). Default: true */
|
|
88
89
|
sessionReplay?: boolean;
|
|
90
|
+
/**
|
|
91
|
+
* Session-replay capture options (SaaS mode).
|
|
92
|
+
* - `record` (default **true**): auto-start frame recording at cold launch so replays appear out
|
|
93
|
+
* of the box. Set `false` for events-only sessions — you can still record on demand with
|
|
94
|
+
* `ScaleBun.startSession()`.
|
|
95
|
+
* - `captureMode` / `intervalMs` / `quality`: tune capture cadence.
|
|
96
|
+
*/
|
|
97
|
+
replay?: {
|
|
98
|
+
record?: boolean;
|
|
99
|
+
captureMode?: 'navigation' | 'interactions' | 'frequency';
|
|
100
|
+
intervalMs?: number;
|
|
101
|
+
quality?: 'high' | 'normal' | 'low' | 'grayscale';
|
|
102
|
+
};
|
|
89
103
|
/** Event flush interval in ms. Default: 5000 */
|
|
90
104
|
flushIntervalMs?: number;
|
|
91
105
|
/** Max events per flush batch. Default: 1000 */
|
|
@@ -234,7 +248,6 @@ export interface ExportResult {
|
|
|
234
248
|
* await ScaleBun.init({
|
|
235
249
|
* projectId: 'proj_xxx',
|
|
236
250
|
* publishableKey: 'pk_xxx',
|
|
237
|
-
* apiBaseUrl: 'https://api.scalebun.com',
|
|
238
251
|
* });
|
|
239
252
|
* ```
|
|
240
253
|
*
|
|
@@ -243,7 +256,6 @@ export interface ExportResult {
|
|
|
243
256
|
* await ScaleBun.init({
|
|
244
257
|
* projectId: 'proj_xxx',
|
|
245
258
|
* publishableKey: 'pk_xxx',
|
|
246
|
-
* apiBaseUrl: 'https://api.scalebun.com',
|
|
247
259
|
* debug: true,
|
|
248
260
|
* });
|
|
249
261
|
* ```
|
|
@@ -254,8 +266,9 @@ export interface SimplifiedInitConfig {
|
|
|
254
266
|
/** Publishable API key from dashboard */
|
|
255
267
|
publishableKey: string;
|
|
256
268
|
/**
|
|
257
|
-
*
|
|
258
|
-
*
|
|
269
|
+
* @deprecated The endpoint is LOCKED to the ScaleBun cloud. Any value passed here is accepted
|
|
270
|
+
* (for backward compatibility) but ignored — the bootstrapper always uses the fixed
|
|
271
|
+
* `DEFAULT_API_BASE_URL`. To target a different backend, change that constant at build time.
|
|
259
272
|
*/
|
|
260
273
|
apiBaseUrl?: string;
|
|
261
274
|
|
|
@@ -271,9 +284,23 @@ export interface SimplifiedInitConfig {
|
|
|
271
284
|
/** @deprecated Use desktopDebug instead. */
|
|
272
285
|
debug?: DebugConnectionConfig;
|
|
273
286
|
|
|
274
|
-
/** Enable session replay capture. Default: true */
|
|
287
|
+
/** Enable session replay capture (feature on/off). Default: true */
|
|
275
288
|
sessionReplay?: boolean;
|
|
276
289
|
|
|
290
|
+
/**
|
|
291
|
+
* Session-replay capture options (SaaS mode).
|
|
292
|
+
* - `record` (default **true**): auto-start frame recording at cold launch so replays appear out
|
|
293
|
+
* of the box. Set `false` for events-only sessions — you can still record on demand with
|
|
294
|
+
* `ScaleBun.startSession()`.
|
|
295
|
+
* - `captureMode` / `intervalMs` / `quality`: tune capture cadence.
|
|
296
|
+
*/
|
|
297
|
+
replay?: {
|
|
298
|
+
record?: boolean;
|
|
299
|
+
captureMode?: 'navigation' | 'interactions' | 'frequency';
|
|
300
|
+
intervalMs?: number;
|
|
301
|
+
quality?: 'high' | 'normal' | 'low' | 'grayscale';
|
|
302
|
+
};
|
|
303
|
+
|
|
277
304
|
/** SDK-wide privacy settings */
|
|
278
305
|
privacy?: PrivacyConfig;
|
|
279
306
|
|
|
@@ -23,8 +23,24 @@ export interface Spec extends TurboModule {
|
|
|
23
23
|
/** DEV/TEST only: crash the process so the next launch can drain it. */
|
|
24
24
|
crashNow(): Promise<boolean>;
|
|
25
25
|
|
|
26
|
+
/**
|
|
27
|
+
* Record which session is live so a crash can name it.
|
|
28
|
+
*
|
|
29
|
+
* Called once per session. Native writes it to crash-safe storage BEFORE any crash can happen —
|
|
30
|
+
* a fatal handler cannot call back into JS to ask.
|
|
31
|
+
*/
|
|
32
|
+
setActiveSessionId(sessionId: string): Promise<boolean>;
|
|
33
|
+
|
|
26
34
|
/** Return the previous run's crash record (or null), then clear it. */
|
|
27
35
|
drainPendingCrash(): Promise<Object>;
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Delete a delivered crash by its stable id.
|
|
39
|
+
*
|
|
40
|
+
* Called ONLY after the backend has accepted it. The read is non-destructive precisely so this
|
|
41
|
+
* can be the moment of deletion — a failed upload must leave the durable copy in place.
|
|
42
|
+
*/
|
|
43
|
+
clearPendingCrash(crashId: string): Promise<boolean>;
|
|
28
44
|
}
|
|
29
45
|
|
|
30
46
|
/**
|