@multiplayer-app/session-recorder-react-native 0.0.1-beta.1 → 0.0.1-beta.11

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 (162) hide show
  1. package/SessionRecorderNative.podspec +29 -0
  2. package/android/build.gradle +32 -0
  3. package/copy-react-native-dist.sh +4 -10
  4. package/dist/components/MaskableComponent.d.ts +22 -0
  5. package/dist/components/MaskableComponent.js +1 -0
  6. package/dist/components/MaskableComponent.js.map +1 -0
  7. package/dist/components/MaskableTextInput.d.ts +14 -0
  8. package/dist/components/MaskableTextInput.js +1 -0
  9. package/dist/components/MaskableTextInput.js.map +1 -0
  10. package/dist/components/SessionRecorderWidget/FinalPopover.d.ts +11 -0
  11. package/dist/components/SessionRecorderWidget/FinalPopover.js +1 -0
  12. package/dist/components/SessionRecorderWidget/FinalPopover.js.map +1 -0
  13. package/dist/components/SessionRecorderWidget/FloatingButton.d.ts +8 -0
  14. package/dist/components/SessionRecorderWidget/FloatingButton.js +1 -0
  15. package/dist/components/SessionRecorderWidget/FloatingButton.js.map +1 -0
  16. package/dist/components/SessionRecorderWidget/InitialPopover.d.ts +13 -0
  17. package/dist/components/SessionRecorderWidget/InitialPopover.js +1 -0
  18. package/dist/components/SessionRecorderWidget/InitialPopover.js.map +1 -0
  19. package/dist/components/SessionRecorderWidget/ModalContainer.d.ts +8 -0
  20. package/dist/components/SessionRecorderWidget/ModalContainer.js +1 -0
  21. package/dist/components/SessionRecorderWidget/ModalContainer.js.map +1 -0
  22. package/dist/components/SessionRecorderWidget/ModalHeader.d.ts +6 -0
  23. package/dist/components/SessionRecorderWidget/ModalHeader.js +1 -0
  24. package/dist/components/SessionRecorderWidget/ModalHeader.js.map +1 -0
  25. package/dist/components/SessionRecorderWidget/SessionRecorderWidget.d.ts +5 -0
  26. package/dist/components/SessionRecorderWidget/SessionRecorderWidget.js +1 -0
  27. package/dist/components/SessionRecorderWidget/SessionRecorderWidget.js.map +1 -0
  28. package/dist/components/SessionRecorderWidget/icons.d.ts +11 -0
  29. package/dist/components/SessionRecorderWidget/icons.js +1 -0
  30. package/dist/components/SessionRecorderWidget/icons.js.map +1 -0
  31. package/dist/components/SessionRecorderWidget/index.d.ts +2 -0
  32. package/dist/components/SessionRecorderWidget/index.js +1 -0
  33. package/dist/components/SessionRecorderWidget/index.js.map +1 -0
  34. package/dist/components/SessionRecorderWidget/styles.d.ts +145 -0
  35. package/dist/components/SessionRecorderWidget/styles.js +1 -0
  36. package/dist/components/SessionRecorderWidget/styles.js.map +1 -0
  37. package/dist/components/index.d.ts +2 -0
  38. package/dist/components/index.js +1 -1
  39. package/dist/components/index.js.map +1 -1
  40. package/dist/config/defaults.js +1 -1
  41. package/dist/config/defaults.js.map +1 -1
  42. package/dist/config/masking.js +1 -1
  43. package/dist/config/masking.js.map +1 -1
  44. package/dist/context/SessionRecorderContext.d.ts +5 -3
  45. package/dist/context/SessionRecorderContext.js +1 -1
  46. package/dist/context/SessionRecorderContext.js.map +1 -1
  47. package/dist/index.d.ts +0 -1
  48. package/dist/index.js +1 -1
  49. package/dist/index.js.map +1 -1
  50. package/dist/native/ScreenMasking.d.ts +21 -0
  51. package/dist/native/ScreenMasking.js +1 -0
  52. package/dist/native/ScreenMasking.js.map +1 -0
  53. package/dist/native/SessionRecorderNative.d.ts +21 -0
  54. package/dist/native/SessionRecorderNative.js +1 -0
  55. package/dist/native/SessionRecorderNative.js.map +1 -0
  56. package/dist/patch/xhr.js +1 -1
  57. package/dist/patch/xhr.js.map +1 -1
  58. package/dist/recorder/screenRecorder.d.ts +1 -0
  59. package/dist/recorder/screenRecorder.js +1 -1
  60. package/dist/recorder/screenRecorder.js.map +1 -1
  61. package/dist/recorder/screenshotManager.d.ts +10 -0
  62. package/dist/recorder/screenshotManager.js +1 -0
  63. package/dist/recorder/screenshotManager.js.map +1 -0
  64. package/dist/services/screenMaskingService.d.ts +39 -0
  65. package/dist/services/screenMaskingService.js +1 -0
  66. package/dist/services/screenMaskingService.js.map +1 -0
  67. package/dist/services/storage.service.d.ts +18 -2
  68. package/dist/services/storage.service.js +1 -1
  69. package/dist/services/storage.service.js.map +1 -1
  70. package/dist/session-recorder.d.ts +2 -1
  71. package/dist/session-recorder.js +1 -1
  72. package/dist/session-recorder.js.map +1 -1
  73. package/dist/types/session-recorder.d.ts +6 -0
  74. package/dist/types/session-recorder.js.map +1 -1
  75. package/dist/utils/componentRegistry.d.ts +64 -0
  76. package/dist/utils/componentRegistry.js +1 -0
  77. package/dist/utils/componentRegistry.js.map +1 -0
  78. package/dist/utils/nativeModuleTest.d.ts +8 -0
  79. package/dist/utils/nativeModuleTest.js +1 -0
  80. package/dist/utils/nativeModuleTest.js.map +1 -0
  81. package/dist/utils/platform.d.ts +3 -0
  82. package/dist/utils/reactNativeHierarchyExtractor.d.ts +38 -0
  83. package/dist/utils/reactNativeHierarchyExtractor.js +1 -0
  84. package/dist/utils/reactNativeHierarchyExtractor.js.map +1 -0
  85. package/dist/utils/screenshotMasker.d.ts +96 -0
  86. package/dist/utils/screenshotMasker.js +1 -0
  87. package/dist/utils/screenshotMasker.js.map +1 -0
  88. package/dist/utils/viewHierarchyTracker.d.ts +89 -0
  89. package/dist/utils/viewHierarchyTracker.js +1 -0
  90. package/dist/utils/viewHierarchyTracker.js.map +1 -0
  91. package/ios/SessionRecorderNative.m +17 -0
  92. package/ios/SessionRecorderNative.podspec +26 -0
  93. package/ios/SessionRecorderNative.swift +205 -0
  94. package/package.json +22 -7
  95. package/react-native.config.js +15 -0
  96. package/RRWEB_INTEGRATION.md +0 -336
  97. package/VIEWSHOT_INTEGRATION_TEST.md +0 -123
  98. package/babel.config.js +0 -13
  99. package/dist/components/GestureCaptureWrapper.d.ts +0 -6
  100. package/dist/components/GestureCaptureWrapper.js +0 -1
  101. package/dist/components/GestureCaptureWrapper.js.map +0 -1
  102. package/dist/expo.d.ts +0 -7
  103. package/dist/expo.js +0 -1
  104. package/dist/expo.js.map +0 -1
  105. package/dist/otel/instrumentations/gestureInstrumentation.d.ts +0 -15
  106. package/dist/otel/instrumentations/gestureInstrumentation.js +0 -1
  107. package/dist/otel/instrumentations/gestureInstrumentation.js.map +0 -1
  108. package/dist/otel/instrumentations/reactNativeInstrumentation.d.ts +0 -8
  109. package/dist/otel/instrumentations/reactNativeInstrumentation.js +0 -1
  110. package/dist/otel/instrumentations/reactNativeInstrumentation.js.map +0 -1
  111. package/dist/otel/instrumentations/reactNavigationInstrumentation.d.ts +0 -13
  112. package/dist/otel/instrumentations/reactNavigationInstrumentation.js +0 -1
  113. package/dist/otel/instrumentations/reactNavigationInstrumentation.js.map +0 -1
  114. package/dist/recorder/gestureHandlerRecorder.d.ts +0 -19
  115. package/dist/recorder/gestureHandlerRecorder.js +0 -1
  116. package/dist/recorder/gestureHandlerRecorder.js.map +0 -1
  117. package/dist/types/rrweb.d.ts +0 -118
  118. package/dist/types/rrweb.js +0 -1
  119. package/dist/types/rrweb.js.map +0 -1
  120. package/scripts/generate-app-metadata.js +0 -173
  121. package/src/components/GestureCaptureWrapper/GestureCaptureWrapper.tsx +0 -86
  122. package/src/components/GestureCaptureWrapper/index.ts +0 -1
  123. package/src/components/ScreenRecorderView/ScreenRecorderView.tsx +0 -72
  124. package/src/components/ScreenRecorderView/index.ts +0 -1
  125. package/src/components/index.ts +0 -1
  126. package/src/config/constants.ts +0 -60
  127. package/src/config/defaults.ts +0 -82
  128. package/src/config/index.ts +0 -6
  129. package/src/config/masking.ts +0 -27
  130. package/src/config/session-recorder.ts +0 -55
  131. package/src/config/validators.ts +0 -31
  132. package/src/context/SessionRecorderContext.tsx +0 -75
  133. package/src/expo.ts +0 -11
  134. package/src/index.ts +0 -17
  135. package/src/otel/helpers.ts +0 -275
  136. package/src/otel/index.ts +0 -138
  137. package/src/otel/instrumentations/index.ts +0 -115
  138. package/src/patch/index.ts +0 -1
  139. package/src/patch/xhr.ts +0 -142
  140. package/src/recorder/eventExporter.ts +0 -141
  141. package/src/recorder/gestureRecorder.ts +0 -498
  142. package/src/recorder/index.ts +0 -179
  143. package/src/recorder/navigationTracker.ts +0 -449
  144. package/src/recorder/screenRecorder.ts +0 -498
  145. package/src/services/api.service.ts +0 -203
  146. package/src/services/storage.service.ts +0 -158
  147. package/src/session-recorder.ts +0 -600
  148. package/src/types/expo.d.ts +0 -23
  149. package/src/types/index.ts +0 -28
  150. package/src/types/session-recorder.ts +0 -423
  151. package/src/types/session.ts +0 -65
  152. package/src/utils/app-metadata.ts +0 -31
  153. package/src/utils/index.ts +0 -8
  154. package/src/utils/logger.ts +0 -225
  155. package/src/utils/platform.ts +0 -384
  156. package/src/utils/request-utils.ts +0 -61
  157. package/src/utils/rrweb-events.ts +0 -309
  158. package/src/utils/session.ts +0 -18
  159. package/src/utils/time.ts +0 -17
  160. package/src/utils/type-utils.ts +0 -75
  161. package/src/version.ts +0 -1
  162. package/tsconfig.json +0 -24
@@ -1,86 +0,0 @@
1
- import React, { ReactNode, useCallback, useMemo } from 'react'
2
- import { Gesture, GestureDetector, GestureHandlerRootView } from 'react-native-gesture-handler'
3
-
4
- export interface GestureCaptureWrapperProps {
5
- children: ReactNode
6
- onGestureRecord: (gestureType: string, data: any) => void
7
- }
8
-
9
- export const GestureCaptureWrapper: React.FC<GestureCaptureWrapperProps> = ({ children, onGestureRecord }) => {
10
- const recordGesture = useCallback(
11
- (gestureType: string, data: any) => {
12
- // Record with session recorder
13
- onGestureRecord(gestureType, data)
14
- },
15
- [onGestureRecord]
16
- )
17
-
18
- // Create tap gesture
19
- const tapGesture = useMemo(() => {
20
- return Gesture.Tap()
21
- .runOnJS(true)
22
- .onStart((event) => {
23
- recordGesture('tap', {
24
- x: event.x,
25
- y: event.y,
26
- timestamp: Date.now()
27
- })
28
- })
29
- }, [recordGesture])
30
-
31
- // Create pan gesture (for swipes and drags)
32
- const panGesture = useMemo(() => {
33
- return Gesture.Pan()
34
- .runOnJS(true)
35
- .onStart((event) => {
36
- recordGesture('pan_start', {
37
- x: event.x,
38
- y: event.y,
39
- timestamp: Date.now()
40
- })
41
- })
42
- .onUpdate((event) => {
43
- recordGesture('pan_update', {
44
- x: event.x,
45
- y: event.y,
46
- translationX: event.translationX,
47
- translationY: event.translationY,
48
- velocityX: event.velocityX,
49
- velocityY: event.velocityY,
50
- timestamp: Date.now()
51
- })
52
- })
53
- .onEnd((event) => {
54
- recordGesture('pan_end', {
55
- x: event.x,
56
- y: event.y,
57
- translationX: event.translationX,
58
- translationY: event.translationY,
59
- velocityX: event.velocityX,
60
- velocityY: event.velocityY,
61
- timestamp: Date.now()
62
- })
63
- })
64
- }, [recordGesture])
65
-
66
- // Create long press gesture
67
- const longPressGesture = useMemo(() => {
68
- return Gesture.LongPress()
69
- .runOnJS(true)
70
- .minDuration(500)
71
- .onStart((event) => {
72
- recordGesture('long_press', {
73
- x: event.x,
74
- y: event.y,
75
- duration: 500,
76
- timestamp: Date.now()
77
- })
78
- })
79
- }, [recordGesture])
80
-
81
- return (
82
- <GestureHandlerRootView style={{ flex: 1 }}>
83
- <GestureDetector gesture={Gesture.Simultaneous(tapGesture, panGesture, longPressGesture)}>{children}</GestureDetector>
84
- </GestureHandlerRootView>
85
- )
86
- }
@@ -1 +0,0 @@
1
- export * from "./GestureCaptureWrapper";
@@ -1,72 +0,0 @@
1
- import SessionRecorder from '@multiplayer-app/session-recorder-react-native'
2
- import React, { PropsWithChildren, useCallback } from 'react'
3
- import { View } from 'react-native'
4
- import { SessionState } from '../../types'
5
- import { logger } from '../../utils'
6
- import { GestureCaptureWrapper } from '../GestureCaptureWrapper'
7
-
8
- interface ScreenRecorderViewProps extends PropsWithChildren {}
9
-
10
- export const ScreenRecorderView = ({ children }: ScreenRecorderViewProps) => {
11
- // Set up gesture recording callback
12
- const handleGestureRecord = useCallback((gestureType: string, data: any) => {
13
- if (SessionRecorder.sessionState !== SessionState.started) {
14
- logger.debug('SessionRecorderContext', 'Gesture recording skipped', {
15
- client: !!SessionRecorder.sessionState,
16
- sessionState: SessionRecorder.sessionState
17
- })
18
- return
19
- }
20
- logger.debug('SessionRecorderContext', 'Gesture recorded', { gestureType, data })
21
- try {
22
- // Record gesture as appropriate touch events
23
- switch (gestureType) {
24
- case 'tap':
25
- // For tap, record both touch start and end
26
- logger.debug('SessionRecorderContext', 'Recording tap as touch start + end')
27
- SessionRecorder.recordTouchStart?.(data.x, data.y, undefined, 1.0)
28
- SessionRecorder.recordTouchEnd?.(data.x, data.y, undefined, 1.0)
29
- break
30
-
31
- case 'pan_start':
32
- logger.debug('SessionRecorderContext', 'Recording pan_start as touch start')
33
- SessionRecorder.recordTouchStart?.(data.x, data.y, undefined, 1.0)
34
- break
35
-
36
- case 'pan_update':
37
- logger.debug('SessionRecorderContext', 'Recording pan_update as touch move')
38
- SessionRecorder.recordTouchMove?.(data.x, data.y, undefined, 1.0)
39
- break
40
-
41
- case 'pan_end':
42
- logger.debug('SessionRecorderContext', 'Recording pan_end as touch end')
43
- SessionRecorder.recordTouchEnd?.(data.x, data.y, undefined, 1.0)
44
- break
45
-
46
- case 'long_press':
47
- logger.debug('SessionRecorderContext', 'Recording long_press as touch start + end')
48
- SessionRecorder.recordTouchStart?.(data.x, data.y, undefined, 1.0)
49
- SessionRecorder.recordTouchEnd?.(data.x, data.y, undefined, 1.0)
50
- break
51
- default:
52
- }
53
- } catch (error) {
54
- logger.error('SessionRecorderContext', 'Failed to record gesture event', error)
55
- }
56
- }, [])
57
-
58
- // Callback ref to set the viewshot ref immediately when available
59
- const setViewShotRef = (ref: View | null) => {
60
- if (ref) {
61
- SessionRecorder.setViewShotRef?.(ref)
62
- }
63
- }
64
-
65
- return (
66
- <GestureCaptureWrapper onGestureRecord={handleGestureRecord}>
67
- <View ref={setViewShotRef} style={{ flex: 1 }}>
68
- {children}
69
- </View>
70
- </GestureCaptureWrapper>
71
- )
72
- }
@@ -1 +0,0 @@
1
- export * from "./ScreenRecorderView";
@@ -1 +0,0 @@
1
- export * from './GestureCaptureWrapper'
@@ -1,60 +0,0 @@
1
-
2
- export const OTEL_MP_SAMPLE_TRACE_RATIO = 0.15
3
-
4
- export const SESSION_ID_PROP_NAME = 'multiplayer-session-id'
5
-
6
- export const SESSION_SHORT_ID_PROP_NAME = 'multiplayer-session-short-id'
7
-
8
- export const SESSION_CONTINUOUS_DEBUGGING_PROP_NAME = 'multiplayer-session-continuous-debugging'
9
-
10
- export const SESSION_STATE_PROP_NAME = 'multiplayer-session-state'
11
-
12
- export const SESSION_TYPE_PROP_NAME = 'multiplayer-session-type'
13
-
14
- export const SESSION_PROP_NAME = 'multiplayer-session-data'
15
-
16
- export const SESSION_STARTED_EVENT = 'debug-session:started'
17
-
18
- export const SESSION_STOPPED_EVENT = 'debug-session:stopped'
19
-
20
- export const SESSION_SUBSCRIBE_EVENT = 'debug-session:subscribe'
21
-
22
- export const SESSION_UNSUBSCRIBE_EVENT = 'debug-session:unsubscribe'
23
-
24
- export const SESSION_AUTO_CREATED = 'debug-session:auto-created'
25
-
26
- export const SESSION_ADD_EVENT = 'debug-session:rrweb:add-event'
27
-
28
- export const DEFAULT_MAX_HTTP_CAPTURING_PAYLOAD_SIZE = 100000
29
-
30
- export const SESSION_RESPONSE = 'multiplayer-debug-session-response'
31
-
32
- export const CONTINUOUS_DEBUGGING_TIMEOUT = 60000 // 1 minutes
33
-
34
- export const DEBUG_SESSION_MAX_DURATION_SECONDS = 10 * 60 + 30 // TODO: move to shared config otel core
35
-
36
- // // Package version - injected by webpack during build
37
- // declare const PACKAGE_VERSION: string
38
- // export const PACKAGE_VERSION_EXPORT = PACKAGE_VERSION || '1.0.0'
39
-
40
-
41
- // Regex patterns for OpenTelemetry ignore URLs
42
- export const OTEL_IGNORE_URLS = [
43
- // Traces endpoint
44
- /.*\/v1\/traces/,
45
- // Debug sessions endpoints
46
- /.*\/v0\/radar\/debug-sessions\/start$/,
47
- /.*\/v0\/radar\/debug-sessions\/[^/]+\/stop$/,
48
- /.*\/v0\/radar\/debug-sessions\/[^/]+\/cancel$/,
49
-
50
- // Continuous debug sessions endpoints
51
- /.*\/v0\/radar\/continuous-debug-sessions\/start$/,
52
- /.*\/v0\/radar\/continuous-debug-sessions\/[^/]+\/save$/,
53
- /.*\/v0\/radar\/continuous-debug-sessions\/[^/]+\/cancel$/,
54
-
55
- // Remote debug session endpoint
56
- /.*\/v0\/radar\/remote-debug-session\/check$/,
57
-
58
- // Or use a more general pattern to catch all radar API endpoints
59
- // /.*\/v0\/radar\/.*/
60
- ]
@@ -1,82 +0,0 @@
1
- import {
2
- SessionRecorderSdk,
3
- MULTIPLAYER_BASE_API_URL,
4
- MULTIPLAYER_OTEL_DEFAULT_TRACES_EXPORTER_HTTP_URL,
5
- } from '@multiplayer-app/session-recorder-common'
6
- import {
7
- MaskingConfig,
8
- SessionRecorderConfigs,
9
- WidgetButtonPlacement,
10
- WidgetTextOverridesConfig,
11
- } from '../types'
12
- import {
13
- OTEL_MP_SAMPLE_TRACE_RATIO,
14
- DEFAULT_MAX_HTTP_CAPTURING_PAYLOAD_SIZE,
15
- } from './constants'
16
- const { mask, sensitiveFields, sensitiveHeaders } = SessionRecorderSdk
17
-
18
- export const DEFAULT_MASKING_CONFIG: MaskingConfig = {
19
- isContentMaskingEnabled: true,
20
- maskBody: mask(sensitiveFields),
21
- maskHeaders: mask(sensitiveHeaders),
22
- maskBodyFieldsList: sensitiveFields,
23
- maskHeadersList: sensitiveHeaders,
24
- headersToInclude: [],
25
- headersToExclude: [],
26
- }
27
-
28
- export const DEFAULT_WIDGET_TEXT_CONFIG: WidgetTextOverridesConfig = {
29
- initialTitleWithContinuous: 'Encountered an issue?',
30
- initialTitleWithoutContinuous: 'Encountered an issue?',
31
- initialDescriptionWithContinuous: 'Record your session so we can see the problem and fix it faster.',
32
- initialDescriptionWithoutContinuous: 'Record your session so we can see the problem and fix it faster.',
33
- continuousRecordingLabel: 'Continuous recording',
34
- startRecordingButtonText: 'Start recording',
35
- finalTitle: 'Done recording?',
36
- finalDescription: 'You can also add a quick note with extra context, expectations, or questions. Thank you!',
37
- commentPlaceholder: 'Add a message...',
38
- saveButtonText: 'Submit recording',
39
- cancelButtonText: 'Cancel recording',
40
- continuousOverlayTitle: 'Save time, skip the reproductions',
41
- continuousOverlayDescription: 'We keep a rolling record of your recent activity. If something doesn’t work as expected, just save the recording and continue working. No need to worry about exceptions and errors - we automatically save recordings for those!',
42
- saveLastSnapshotButtonText: 'Save recording',
43
- submitDialogTitle: 'Save recording',
44
- submitDialogSubtitle: 'This full-stack session recording will be saved directly to your selected Multiplayer project. All data is automatically correlated end-to-end.',
45
- submitDialogCommentLabel: 'You can also add context, comments, or notes.',
46
- submitDialogCommentPlaceholder: 'Add a message...',
47
- submitDialogSubmitText: 'Save',
48
- submitDialogCancelText: 'Cancel',
49
- }
50
-
51
- export const BASE_CONFIG: Required<SessionRecorderConfigs> = {
52
- apiKey: '',
53
-
54
- version: '',
55
- application: '',
56
- environment: '',
57
-
58
- showWidget: true,
59
- showContinuousRecording: true,
60
- widgetButtonPlacement: WidgetButtonPlacement.bottomRight,
61
-
62
- usePostMessageFallback: false,
63
- apiBaseUrl: MULTIPLAYER_BASE_API_URL,
64
- exporterEndpoint: MULTIPLAYER_OTEL_DEFAULT_TRACES_EXPORTER_HTTP_URL,
65
-
66
- schemifyDocSpanPayload: true,
67
-
68
- ignoreUrls: [],
69
- propagateTraceHeaderCorsUrls: [],
70
-
71
- sampleTraceRatio: OTEL_MP_SAMPLE_TRACE_RATIO,
72
- maxCapturingHttpPayloadSize: DEFAULT_MAX_HTTP_CAPTURING_PAYLOAD_SIZE,
73
-
74
- captureBody: true,
75
- captureHeaders: true,
76
- masking: DEFAULT_MASKING_CONFIG,
77
- widgetTextOverrides: DEFAULT_WIDGET_TEXT_CONFIG,
78
-
79
- recordScreen: true,
80
- recordGestures: true,
81
- recordNavigation: true,
82
- }
@@ -1,6 +0,0 @@
1
- // Export all config-related functions and constants
2
- export * from './constants'
3
- export * from './defaults'
4
- export * from './validators'
5
- export * from './masking'
6
- export * from './session-recorder'
@@ -1,27 +0,0 @@
1
- import { MaskingConfig } from '../types'
2
- import { DEFAULT_MASKING_CONFIG } from './defaults'
3
- import { isValidArray, isValidBoolean, isValidFunction } from './validators'
4
- import { SessionRecorderSdk } from '@multiplayer-app/session-recorder-common'
5
-
6
- const { mask, sensitiveFields, sensitiveHeaders } = SessionRecorderSdk
7
-
8
- export const getMaskingConfig = (masking?: MaskingConfig): MaskingConfig => {
9
- const baseMasking = DEFAULT_MASKING_CONFIG
10
-
11
- if (typeof masking !== 'object') {
12
- return baseMasking
13
- }
14
-
15
- const maskHeadersList = isValidArray(masking.maskHeadersList, sensitiveHeaders)
16
- const maskBodyFieldsList = isValidArray(masking.maskBodyFieldsList, sensitiveFields)
17
-
18
- return {
19
- maskHeadersList,
20
- maskBodyFieldsList,
21
- headersToInclude: isValidArray(masking.headersToInclude, baseMasking.headersToInclude ?? []),
22
- headersToExclude: isValidArray(masking.headersToExclude, baseMasking.headersToExclude ?? []),
23
- isContentMaskingEnabled: isValidBoolean(masking.isContentMaskingEnabled, baseMasking.isContentMaskingEnabled ?? true),
24
- maskBody: isValidFunction(masking.maskBody, mask(maskBodyFieldsList)),
25
- maskHeaders: isValidFunction(masking.maskHeaders, mask(maskHeadersList)),
26
- }
27
- }
@@ -1,55 +0,0 @@
1
- import { SessionRecorderConfigs, SessionRecorderOptions, WidgetButtonPlacement } from '../types'
2
- import { BASE_CONFIG } from './defaults'
3
- import { getMaskingConfig } from './masking'
4
- import {
5
- isValidString,
6
- isValidNumber,
7
- isValidBoolean,
8
- isValidArray,
9
- isValidEnum,
10
- } from './validators'
11
-
12
- const getWidgetTextOverridesConfig = (config: any, defaultConfig: any) => {
13
- if (!config || typeof config !== 'object') {
14
- return defaultConfig
15
- }
16
- return Object.keys(defaultConfig).reduce((acc, key) => {
17
- acc[key] = isValidString(config[key], defaultConfig[key])
18
- return acc
19
- }, {} as Record<string, any>)
20
- }
21
-
22
- export const getSessionRecorderConfig = (c: SessionRecorderOptions): SessionRecorderConfigs => {
23
- if (!c) {
24
- return BASE_CONFIG
25
- }
26
-
27
- return {
28
- apiKey: isValidString(c.apiKey, BASE_CONFIG.apiKey),
29
- version: isValidString(c.version, BASE_CONFIG.version),
30
- application: isValidString(c.application, BASE_CONFIG.application),
31
- environment: isValidString(c.environment, BASE_CONFIG.environment),
32
-
33
- exporterEndpoint: isValidString(c.exporterEndpoint, BASE_CONFIG.exporterEndpoint),
34
- apiBaseUrl: isValidString(c.apiBaseUrl, BASE_CONFIG.apiBaseUrl),
35
- usePostMessageFallback: isValidBoolean(c.usePostMessageFallback, BASE_CONFIG.usePostMessageFallback),
36
-
37
- showWidget: isValidBoolean(c.showWidget, BASE_CONFIG.showWidget),
38
- showContinuousRecording: isValidBoolean(c.showContinuousRecording, BASE_CONFIG.showContinuousRecording),
39
- widgetButtonPlacement: isValidEnum<WidgetButtonPlacement>(c.widgetButtonPlacement, BASE_CONFIG.widgetButtonPlacement, Object.values(WidgetButtonPlacement) as WidgetButtonPlacement[]),
40
- ignoreUrls: isValidArray(c.ignoreUrls, BASE_CONFIG.ignoreUrls),
41
- sampleTraceRatio: isValidNumber(c.sampleTraceRatio, BASE_CONFIG.sampleTraceRatio),
42
- propagateTraceHeaderCorsUrls: c.propagateTraceHeaderCorsUrls || BASE_CONFIG.propagateTraceHeaderCorsUrls,
43
- schemifyDocSpanPayload: isValidBoolean(c.schemifyDocSpanPayload, BASE_CONFIG.schemifyDocSpanPayload),
44
- maxCapturingHttpPayloadSize: isValidNumber(c.maxCapturingHttpPayloadSize, BASE_CONFIG.maxCapturingHttpPayloadSize),
45
-
46
- masking: getMaskingConfig(c.masking),
47
- captureBody: isValidBoolean(c.captureBody, BASE_CONFIG.captureBody),
48
- captureHeaders: isValidBoolean(c.captureHeaders, BASE_CONFIG.captureHeaders),
49
- widgetTextOverrides: getWidgetTextOverridesConfig(c.widgetTextOverrides, BASE_CONFIG.widgetTextOverrides),
50
-
51
- recordScreen: isValidBoolean(c.recordScreen, BASE_CONFIG.recordScreen),
52
- recordGestures: isValidBoolean(c.recordGestures, BASE_CONFIG.recordGestures),
53
- recordNavigation: isValidBoolean(c.recordNavigation, BASE_CONFIG.recordNavigation),
54
- }
55
- }
@@ -1,31 +0,0 @@
1
- /**
2
- * Validation helper functions for configuration objects
3
- */
4
-
5
- export const isValidStringOrRegExp = (value: string | RegExp | undefined, defaultValue: string | RegExp) => {
6
- return typeof value === 'string' || value instanceof RegExp ? value : defaultValue
7
- }
8
-
9
- export const isValidString = <T extends string>(value: string | undefined | T, defaultValue: string) => {
10
- return typeof value === 'string' ? value.trim() : defaultValue
11
- }
12
-
13
- export const isValidNumber = (value: number | undefined, defaultValue: number) => {
14
- return typeof value === 'number' ? value : defaultValue
15
- }
16
-
17
- export const isValidBoolean = (value: boolean | undefined, defaultValue: boolean) => {
18
- return typeof value === 'boolean' ? value : defaultValue
19
- }
20
-
21
- export const isValidArray = (value: any[] | undefined, defaultValue: any[]) => {
22
- return Array.isArray(value) ? value : defaultValue
23
- }
24
-
25
- export const isValidEnum = <T>(value: any | T, defaultValue: T, enumValues: T[]): T => {
26
- return enumValues.includes(value as T) ? value as T : defaultValue
27
- }
28
-
29
- export const isValidFunction = (value: any, defaultValue: any) => {
30
- return typeof value === 'function' ? value : defaultValue
31
- }
@@ -1,75 +0,0 @@
1
- import React, { createContext, useContext, PropsWithChildren, useState, useEffect, useRef } from 'react'
2
- import { Pressable, Text, View } from 'react-native'
3
- import { SessionRecorderOptions, SessionState } from '../types'
4
- import SessionRecorder from '../session-recorder'
5
- import sessionRecorder from '../session-recorder'
6
- import { ScreenRecorderView } from '../components/ScreenRecorderView'
7
-
8
- interface SessionRecorderContextType {
9
- instance: typeof SessionRecorder
10
- }
11
-
12
- const SessionRecorderContext = createContext<SessionRecorderContextType | null>(null)
13
-
14
- export interface SessionRecorderProviderProps extends PropsWithChildren {
15
- options: SessionRecorderOptions
16
- }
17
-
18
- export const SessionRecorderProvider: React.FC<SessionRecorderProviderProps> = ({ children, options }) => {
19
- const [sessionState, setSessionState] = useState<SessionState | null>(null)
20
- const optionsRef = useRef<string>()
21
-
22
- useEffect(() => {
23
- const newOptions = JSON.stringify(options)
24
- if (optionsRef.current === JSON.stringify(options)) return
25
- optionsRef.current = newOptions
26
- SessionRecorder.init(options)
27
- }, [options])
28
-
29
- useEffect(() => {
30
- setSessionState(SessionRecorder.sessionState)
31
- SessionRecorder.on('state-change', (state: SessionState) => {
32
- setSessionState(state)
33
- })
34
- }, [])
35
-
36
- const onToggleSession = () => {
37
- if (SessionRecorder.sessionState === SessionState.started) {
38
- SessionRecorder.stop()
39
- } else {
40
- SessionRecorder.start()
41
- }
42
- }
43
-
44
- return (
45
- <SessionRecorderContext.Provider value={{ instance: sessionRecorder }}>
46
- <ScreenRecorderView>{children}</ScreenRecorderView>
47
- <Pressable onPress={onToggleSession}>
48
- <View
49
- style={{
50
- position: 'absolute',
51
- right: 0,
52
- bottom: 100,
53
- width: 48,
54
- height: 48,
55
- paddingTop: 16,
56
- paddingLeft: 10,
57
- backgroundColor: 'red',
58
- borderTopLeftRadius: 24,
59
- borderBottomLeftRadius: 24
60
- }}
61
- >
62
- <Text style={{ color: 'white' }}>{sessionState === SessionState.started ? 'Stop' : 'Start'}</Text>
63
- </View>
64
- </Pressable>
65
- </SessionRecorderContext.Provider>
66
- )
67
- }
68
-
69
- export const useSessionRecorder = (): SessionRecorderContextType => {
70
- const context = useContext(SessionRecorderContext)
71
- if (!context) {
72
- throw new Error('useSessionRecorder must be used within a SessionRecorderProvider')
73
- }
74
- return context
75
- }
package/src/expo.ts DELETED
@@ -1,11 +0,0 @@
1
- import './patch'
2
- import SessionRecorder from './session-recorder'
3
- export * from '@multiplayer-app/session-recorder-common'
4
- export * from './context/SessionRecorderContext'
5
-
6
- export { SessionRecorder }
7
- // Export the instance as default
8
- export default SessionRecorder
9
-
10
- // Export Expo-specific utilities
11
- export { isExpoEnvironment, getPlatformAttributes } from './utils/platform'
package/src/index.ts DELETED
@@ -1,17 +0,0 @@
1
- import './patch'
2
- import SessionRecorder from './session-recorder'
3
- export * from '@multiplayer-app/session-recorder-common'
4
- export * from './context/SessionRecorderContext'
5
-
6
- // Export platform utilities including app metadata configuration
7
- export {
8
- detectPlatform,
9
- isExpoEnvironment,
10
- configureAppMetadata,
11
- getPlatformAttributes,
12
- getConfiguredAppMetadata,
13
- } from './utils/platform'
14
-
15
- export { SessionRecorder }
16
- // Export the instance as default
17
- export default SessionRecorder