@kubesense/kubesense-browser-rum 1.0.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.
Files changed (540) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +34 -0
  3. package/bundle/chunks/profiler-b64730a2109c3ddbc539-kubesense-rum.js +1 -0
  4. package/bundle/chunks/recorder-9ae532a18bac5f4280da-kubesense-rum.js +1 -0
  5. package/bundle/kubesense-rum.js +1 -0
  6. package/cjs/boot/isBrowserSupported.d.ts +4 -0
  7. package/cjs/boot/isBrowserSupported.js +17 -0
  8. package/cjs/boot/isBrowserSupported.js.map +1 -0
  9. package/cjs/boot/lazyLoadProfiler.d.ts +4 -0
  10. package/cjs/boot/lazyLoadProfiler.js +54 -0
  11. package/cjs/boot/lazyLoadProfiler.js.map +1 -0
  12. package/cjs/boot/lazyLoadRecorder.d.ts +4 -0
  13. package/cjs/boot/lazyLoadRecorder.js +54 -0
  14. package/cjs/boot/lazyLoadRecorder.js.map +1 -0
  15. package/cjs/boot/postStartStrategy.d.ts +33 -0
  16. package/cjs/boot/postStartStrategy.js +98 -0
  17. package/cjs/boot/postStartStrategy.js.map +1 -0
  18. package/cjs/boot/preStartStrategy.d.ts +6 -0
  19. package/cjs/boot/preStartStrategy.js +24 -0
  20. package/cjs/boot/preStartStrategy.js.map +1 -0
  21. package/cjs/boot/profilerApi.d.ts +2 -0
  22. package/cjs/boot/profilerApi.js +53 -0
  23. package/cjs/boot/profilerApi.js.map +1 -0
  24. package/cjs/boot/recorderApi.d.ts +4 -0
  25. package/cjs/boot/recorderApi.js +73 -0
  26. package/cjs/boot/recorderApi.js.map +1 -0
  27. package/cjs/boot/startRecording.d.ts +6 -0
  28. package/cjs/boot/startRecording.js +45 -0
  29. package/cjs/boot/startRecording.js.map +1 -0
  30. package/cjs/domain/deflate/deflateEncoder.d.ts +3 -0
  31. package/cjs/domain/deflate/deflateEncoder.js +110 -0
  32. package/cjs/domain/deflate/deflateEncoder.js.map +1 -0
  33. package/cjs/domain/deflate/deflateWorker.d.ts +30 -0
  34. package/cjs/domain/deflate/deflateWorker.js +104 -0
  35. package/cjs/domain/deflate/deflateWorker.js.map +1 -0
  36. package/cjs/domain/deflate/index.d.ts +3 -0
  37. package/cjs/domain/deflate/index.js +10 -0
  38. package/cjs/domain/deflate/index.js.map +1 -0
  39. package/cjs/domain/getSessionReplayLink.d.ts +2 -0
  40. package/cjs/domain/getSessionReplayLink.js +35 -0
  41. package/cjs/domain/getSessionReplayLink.js.map +1 -0
  42. package/cjs/domain/profiling/profiler.d.ts +7 -0
  43. package/cjs/domain/profiling/profiler.js +244 -0
  44. package/cjs/domain/profiling/profiler.js.map +1 -0
  45. package/cjs/domain/profiling/profilingContext.d.ts +6 -0
  46. package/cjs/domain/profiling/profilingContext.js +28 -0
  47. package/cjs/domain/profiling/profilingContext.js.map +1 -0
  48. package/cjs/domain/profiling/profilingSupported.d.ts +1 -0
  49. package/cjs/domain/profiling/profilingSupported.js +11 -0
  50. package/cjs/domain/profiling/profilingSupported.js.map +1 -0
  51. package/cjs/domain/profiling/test-utils/mockedTrace.d.ts +3 -0
  52. package/cjs/domain/profiling/test-utils/mockedTrace.js +57 -0
  53. package/cjs/domain/profiling/test-utils/mockedTrace.js.map +1 -0
  54. package/cjs/domain/profiling/transport/assembly.d.ts +21 -0
  55. package/cjs/domain/profiling/transport/assembly.js +45 -0
  56. package/cjs/domain/profiling/transport/assembly.js.map +1 -0
  57. package/cjs/domain/profiling/transport/buildProfileEventAttributes.d.ts +25 -0
  58. package/cjs/domain/profiling/transport/buildProfileEventAttributes.js +50 -0
  59. package/cjs/domain/profiling/transport/buildProfileEventAttributes.js.map +1 -0
  60. package/cjs/domain/profiling/types/index.d.ts +2 -0
  61. package/cjs/domain/profiling/types/index.js +3 -0
  62. package/cjs/domain/profiling/types/index.js.map +1 -0
  63. package/cjs/domain/profiling/types/profilerApi.types.d.ts +58 -0
  64. package/cjs/domain/profiling/types/profilerApi.types.js +5 -0
  65. package/cjs/domain/profiling/types/profilerApi.types.js.map +1 -0
  66. package/cjs/domain/profiling/types/rumProfiler.types.d.ts +72 -0
  67. package/cjs/domain/profiling/types/rumProfiler.types.js +3 -0
  68. package/cjs/domain/profiling/types/rumProfiler.types.js.map +1 -0
  69. package/cjs/domain/profiling/utils/getCustomOrDefaultViewName.d.ts +1 -0
  70. package/cjs/domain/profiling/utils/getCustomOrDefaultViewName.js +7 -0
  71. package/cjs/domain/profiling/utils/getCustomOrDefaultViewName.js.map +1 -0
  72. package/cjs/domain/profiling/utils/getDefaultViewName.d.ts +1 -0
  73. package/cjs/domain/profiling/utils/getDefaultViewName.js +14 -0
  74. package/cjs/domain/profiling/utils/getDefaultViewName.js.map +1 -0
  75. package/cjs/domain/profiling/utils/getNumberOfSamples.d.ts +7 -0
  76. package/cjs/domain/profiling/utils/getNumberOfSamples.js +18 -0
  77. package/cjs/domain/profiling/utils/getNumberOfSamples.js.map +1 -0
  78. package/cjs/domain/record/assembly.d.ts +2 -0
  79. package/cjs/domain/record/assembly.js +16 -0
  80. package/cjs/domain/record/assembly.js.map +1 -0
  81. package/cjs/domain/record/elementsScrollPositions.d.ts +10 -0
  82. package/cjs/domain/record/elementsScrollPositions.js +23 -0
  83. package/cjs/domain/record/elementsScrollPositions.js.map +1 -0
  84. package/cjs/domain/record/eventIds.d.ts +4 -0
  85. package/cjs/domain/record/eventIds.js +16 -0
  86. package/cjs/domain/record/eventIds.js.map +1 -0
  87. package/cjs/domain/record/eventsUtils.d.ts +2 -0
  88. package/cjs/domain/record/eventsUtils.js +15 -0
  89. package/cjs/domain/record/eventsUtils.js.map +1 -0
  90. package/cjs/domain/record/index.d.ts +7 -0
  91. package/cjs/domain/record/index.js +17 -0
  92. package/cjs/domain/record/index.js.map +1 -0
  93. package/cjs/domain/record/internalApi.d.ts +22 -0
  94. package/cjs/domain/record/internalApi.js +57 -0
  95. package/cjs/domain/record/internalApi.js.map +1 -0
  96. package/cjs/domain/record/mutationBatch.d.ts +12 -0
  97. package/cjs/domain/record/mutationBatch.js +44 -0
  98. package/cjs/domain/record/mutationBatch.js.map +1 -0
  99. package/cjs/domain/record/nodeIds.d.ts +15 -0
  100. package/cjs/domain/record/nodeIds.js +32 -0
  101. package/cjs/domain/record/nodeIds.js.map +1 -0
  102. package/cjs/domain/record/record.d.ts +16 -0
  103. package/cjs/domain/record/record.js +90 -0
  104. package/cjs/domain/record/record.js.map +1 -0
  105. package/cjs/domain/record/record.types.d.ts +4 -0
  106. package/cjs/domain/record/record.types.js +3 -0
  107. package/cjs/domain/record/record.types.js.map +1 -0
  108. package/cjs/domain/record/recordingScope.d.ts +19 -0
  109. package/cjs/domain/record/recordingScope.js +13 -0
  110. package/cjs/domain/record/recordingScope.js.map +1 -0
  111. package/cjs/domain/record/serialization/index.d.ts +8 -0
  112. package/cjs/domain/record/serialization/index.js +18 -0
  113. package/cjs/domain/record/serialization/index.js.map +1 -0
  114. package/cjs/domain/record/serialization/serialization.types.d.ts +28 -0
  115. package/cjs/domain/record/serialization/serialization.types.js +3 -0
  116. package/cjs/domain/record/serialization/serialization.types.js.map +1 -0
  117. package/cjs/domain/record/serialization/serializationStats.d.ts +12 -0
  118. package/cjs/domain/record/serialization/serializationStats.js +32 -0
  119. package/cjs/domain/record/serialization/serializationStats.js.map +1 -0
  120. package/cjs/domain/record/serialization/serializationTransaction.d.ts +45 -0
  121. package/cjs/domain/record/serialization/serializationTransaction.js +38 -0
  122. package/cjs/domain/record/serialization/serializationTransaction.js.map +1 -0
  123. package/cjs/domain/record/serialization/serializationUtils.d.ts +18 -0
  124. package/cjs/domain/record/serialization/serializationUtils.js +88 -0
  125. package/cjs/domain/record/serialization/serializationUtils.js.map +1 -0
  126. package/cjs/domain/record/serialization/serializeAttribute.d.ts +4 -0
  127. package/cjs/domain/record/serialization/serializeAttribute.js +42 -0
  128. package/cjs/domain/record/serialization/serializeAttribute.js.map +1 -0
  129. package/cjs/domain/record/serialization/serializeAttributes.d.ts +7 -0
  130. package/cjs/domain/record/serialization/serializeAttributes.js +167 -0
  131. package/cjs/domain/record/serialization/serializeAttributes.js.map +1 -0
  132. package/cjs/domain/record/serialization/serializeDocument.d.ts +3 -0
  133. package/cjs/domain/record/serialization/serializeDocument.js +11 -0
  134. package/cjs/domain/record/serialization/serializeDocument.js.map +1 -0
  135. package/cjs/domain/record/serialization/serializeNode.d.ts +7 -0
  136. package/cjs/domain/record/serialization/serializeNode.js +154 -0
  137. package/cjs/domain/record/serialization/serializeNode.js.map +1 -0
  138. package/cjs/domain/record/serialization/serializeStyleSheets.d.ts +2 -0
  139. package/cjs/domain/record/serialization/serializeStyleSheets.js +19 -0
  140. package/cjs/domain/record/serialization/serializeStyleSheets.js.map +1 -0
  141. package/cjs/domain/record/shadowRootsController.d.ts +11 -0
  142. package/cjs/domain/record/shadowRootsController.js +45 -0
  143. package/cjs/domain/record/shadowRootsController.js.map +1 -0
  144. package/cjs/domain/record/startFullSnapshots.d.ts +9 -0
  145. package/cjs/domain/record/startFullSnapshots.js +59 -0
  146. package/cjs/domain/record/startFullSnapshots.js.map +1 -0
  147. package/cjs/domain/record/trackers/index.d.ts +12 -0
  148. package/cjs/domain/record/trackers/index.js +27 -0
  149. package/cjs/domain/record/trackers/index.js.map +1 -0
  150. package/cjs/domain/record/trackers/trackFocus.d.ts +5 -0
  151. package/cjs/domain/record/trackers/trackFocus.js +15 -0
  152. package/cjs/domain/record/trackers/trackFocus.js.map +1 -0
  153. package/cjs/domain/record/trackers/trackFrustration.d.ts +7 -0
  154. package/cjs/domain/record/trackers/trackFrustration.js +31 -0
  155. package/cjs/domain/record/trackers/trackFrustration.js.map +1 -0
  156. package/cjs/domain/record/trackers/trackInput.d.ts +4 -0
  157. package/cjs/domain/record/trackers/trackInput.js +104 -0
  158. package/cjs/domain/record/trackers/trackInput.js.map +1 -0
  159. package/cjs/domain/record/trackers/trackMediaInteraction.d.ts +5 -0
  160. package/cjs/domain/record/trackers/trackMediaInteraction.js +29 -0
  161. package/cjs/domain/record/trackers/trackMediaInteraction.js.map +1 -0
  162. package/cjs/domain/record/trackers/trackMouseInteraction.d.ts +5 -0
  163. package/cjs/domain/record/trackers/trackMouseInteraction.js +59 -0
  164. package/cjs/domain/record/trackers/trackMouseInteraction.js.map +1 -0
  165. package/cjs/domain/record/trackers/trackMove.d.ts +9 -0
  166. package/cjs/domain/record/trackers/trackMove.js +55 -0
  167. package/cjs/domain/record/trackers/trackMove.js.map +1 -0
  168. package/cjs/domain/record/trackers/trackMutation.d.ts +11 -0
  169. package/cjs/domain/record/trackers/trackMutation.js +270 -0
  170. package/cjs/domain/record/trackers/trackMutation.js.map +1 -0
  171. package/cjs/domain/record/trackers/trackScroll.d.ts +5 -0
  172. package/cjs/domain/record/trackers/trackScroll.js +48 -0
  173. package/cjs/domain/record/trackers/trackScroll.js.map +1 -0
  174. package/cjs/domain/record/trackers/trackStyleSheet.d.ts +6 -0
  175. package/cjs/domain/record/trackers/trackStyleSheet.js +89 -0
  176. package/cjs/domain/record/trackers/trackStyleSheet.js.map +1 -0
  177. package/cjs/domain/record/trackers/trackViewEnd.d.ts +5 -0
  178. package/cjs/domain/record/trackers/trackViewEnd.js +20 -0
  179. package/cjs/domain/record/trackers/trackViewEnd.js.map +1 -0
  180. package/cjs/domain/record/trackers/trackViewportResize.d.ts +6 -0
  181. package/cjs/domain/record/trackers/trackViewportResize.js +46 -0
  182. package/cjs/domain/record/trackers/trackViewportResize.js.map +1 -0
  183. package/cjs/domain/record/trackers/tracker.types.d.ts +3 -0
  184. package/cjs/domain/record/trackers/tracker.types.js +3 -0
  185. package/cjs/domain/record/trackers/tracker.types.js.map +1 -0
  186. package/cjs/domain/record/viewports.d.ts +20 -0
  187. package/cjs/domain/record/viewports.js +60 -0
  188. package/cjs/domain/record/viewports.js.map +1 -0
  189. package/cjs/domain/replayStats.d.ts +8 -0
  190. package/cjs/domain/replayStats.js +60 -0
  191. package/cjs/domain/replayStats.js.map +1 -0
  192. package/cjs/domain/scriptLoadingError.d.ts +6 -0
  193. package/cjs/domain/scriptLoadingError.js +26 -0
  194. package/cjs/domain/scriptLoadingError.js.map +1 -0
  195. package/cjs/domain/segmentCollection/buildReplayPayload.d.ts +15 -0
  196. package/cjs/domain/segmentCollection/buildReplayPayload.js +26 -0
  197. package/cjs/domain/segmentCollection/buildReplayPayload.js.map +1 -0
  198. package/cjs/domain/segmentCollection/index.d.ts +4 -0
  199. package/cjs/domain/segmentCollection/index.js +11 -0
  200. package/cjs/domain/segmentCollection/index.js.map +1 -0
  201. package/cjs/domain/segmentCollection/segment.d.ts +16 -0
  202. package/cjs/domain/segmentCollection/segment.js +82 -0
  203. package/cjs/domain/segmentCollection/segment.js.map +1 -0
  204. package/cjs/domain/segmentCollection/segmentCollection.d.ts +31 -0
  205. package/cjs/domain/segmentCollection/segmentCollection.js +113 -0
  206. package/cjs/domain/segmentCollection/segmentCollection.js.map +1 -0
  207. package/cjs/domain/segmentCollection/startSegmentTelemetry.d.ts +6 -0
  208. package/cjs/domain/segmentCollection/startSegmentTelemetry.js +47 -0
  209. package/cjs/domain/segmentCollection/startSegmentTelemetry.js.map +1 -0
  210. package/cjs/domain/startRecordBridge.d.ts +5 -0
  211. package/cjs/domain/startRecordBridge.js +17 -0
  212. package/cjs/domain/startRecordBridge.js.map +1 -0
  213. package/cjs/domain/startRecorderInitTelemetry.d.ts +15 -0
  214. package/cjs/domain/startRecorderInitTelemetry.js +55 -0
  215. package/cjs/domain/startRecorderInitTelemetry.js.map +1 -0
  216. package/cjs/entries/internal.d.ts +11 -0
  217. package/cjs/entries/internal.js +28 -0
  218. package/cjs/entries/internal.js.map +1 -0
  219. package/cjs/entries/internalSynthetics.d.ts +2 -0
  220. package/cjs/entries/internalSynthetics.js +27 -0
  221. package/cjs/entries/internalSynthetics.js.map +1 -0
  222. package/cjs/entries/main.d.ts +23 -0
  223. package/cjs/entries/main.js +35 -0
  224. package/cjs/entries/main.js.map +1 -0
  225. package/cjs/types/index.d.ts +2 -0
  226. package/cjs/types/index.js +18 -0
  227. package/cjs/types/index.js.map +1 -0
  228. package/cjs/types/sessionReplay.d.ts +703 -0
  229. package/cjs/types/sessionReplay.js +7 -0
  230. package/cjs/types/sessionReplay.js.map +1 -0
  231. package/cjs/types/sessionReplayConstants.d.ts +49 -0
  232. package/cjs/types/sessionReplayConstants.js +49 -0
  233. package/cjs/types/sessionReplayConstants.js.map +1 -0
  234. package/esm/boot/isBrowserSupported.d.ts +4 -0
  235. package/esm/boot/isBrowserSupported.js +14 -0
  236. package/esm/boot/isBrowserSupported.js.map +1 -0
  237. package/esm/boot/lazyLoadProfiler.d.ts +4 -0
  238. package/esm/boot/lazyLoadProfiler.js +18 -0
  239. package/esm/boot/lazyLoadProfiler.js.map +1 -0
  240. package/esm/boot/lazyLoadRecorder.d.ts +4 -0
  241. package/esm/boot/lazyLoadRecorder.js +18 -0
  242. package/esm/boot/lazyLoadRecorder.js.map +1 -0
  243. package/esm/boot/postStartStrategy.d.ts +33 -0
  244. package/esm/boot/postStartStrategy.js +95 -0
  245. package/esm/boot/postStartStrategy.js.map +1 -0
  246. package/esm/boot/preStartStrategy.d.ts +6 -0
  247. package/esm/boot/preStartStrategy.js +21 -0
  248. package/esm/boot/preStartStrategy.js.map +1 -0
  249. package/esm/boot/profilerApi.d.ts +2 -0
  250. package/esm/boot/profilerApi.js +50 -0
  251. package/esm/boot/profilerApi.js.map +1 -0
  252. package/esm/boot/recorderApi.d.ts +4 -0
  253. package/esm/boot/recorderApi.js +70 -0
  254. package/esm/boot/recorderApi.js.map +1 -0
  255. package/esm/boot/startRecording.d.ts +6 -0
  256. package/esm/boot/startRecording.js +42 -0
  257. package/esm/boot/startRecording.js.map +1 -0
  258. package/esm/domain/deflate/deflateEncoder.d.ts +3 -0
  259. package/esm/domain/deflate/deflateEncoder.js +107 -0
  260. package/esm/domain/deflate/deflateEncoder.js.map +1 -0
  261. package/esm/domain/deflate/deflateWorker.d.ts +30 -0
  262. package/esm/domain/deflate/deflateWorker.js +97 -0
  263. package/esm/domain/deflate/deflateWorker.js.map +1 -0
  264. package/esm/domain/deflate/index.d.ts +3 -0
  265. package/esm/domain/deflate/index.js +3 -0
  266. package/esm/domain/deflate/index.js.map +1 -0
  267. package/esm/domain/getSessionReplayLink.d.ts +2 -0
  268. package/esm/domain/getSessionReplayLink.js +32 -0
  269. package/esm/domain/getSessionReplayLink.js.map +1 -0
  270. package/esm/domain/profiling/profiler.d.ts +7 -0
  271. package/esm/domain/profiling/profiler.js +240 -0
  272. package/esm/domain/profiling/profiler.js.map +1 -0
  273. package/esm/domain/profiling/profilingContext.d.ts +6 -0
  274. package/esm/domain/profiling/profilingContext.js +25 -0
  275. package/esm/domain/profiling/profilingContext.js.map +1 -0
  276. package/esm/domain/profiling/profilingSupported.d.ts +1 -0
  277. package/esm/domain/profiling/profilingSupported.js +8 -0
  278. package/esm/domain/profiling/profilingSupported.js.map +1 -0
  279. package/esm/domain/profiling/test-utils/mockedTrace.d.ts +3 -0
  280. package/esm/domain/profiling/test-utils/mockedTrace.js +54 -0
  281. package/esm/domain/profiling/test-utils/mockedTrace.js.map +1 -0
  282. package/esm/domain/profiling/transport/assembly.d.ts +21 -0
  283. package/esm/domain/profiling/transport/assembly.js +42 -0
  284. package/esm/domain/profiling/transport/assembly.js.map +1 -0
  285. package/esm/domain/profiling/transport/buildProfileEventAttributes.d.ts +25 -0
  286. package/esm/domain/profiling/transport/buildProfileEventAttributes.js +47 -0
  287. package/esm/domain/profiling/transport/buildProfileEventAttributes.js.map +1 -0
  288. package/esm/domain/profiling/types/index.d.ts +2 -0
  289. package/esm/domain/profiling/types/index.js +2 -0
  290. package/esm/domain/profiling/types/index.js.map +1 -0
  291. package/esm/domain/profiling/types/profilerApi.types.d.ts +58 -0
  292. package/esm/domain/profiling/types/profilerApi.types.js +4 -0
  293. package/esm/domain/profiling/types/profilerApi.types.js.map +1 -0
  294. package/esm/domain/profiling/types/rumProfiler.types.d.ts +72 -0
  295. package/esm/domain/profiling/types/rumProfiler.types.js +2 -0
  296. package/esm/domain/profiling/types/rumProfiler.types.js.map +1 -0
  297. package/esm/domain/profiling/utils/getCustomOrDefaultViewName.d.ts +1 -0
  298. package/esm/domain/profiling/utils/getCustomOrDefaultViewName.js +3 -0
  299. package/esm/domain/profiling/utils/getCustomOrDefaultViewName.js.map +1 -0
  300. package/esm/domain/profiling/utils/getDefaultViewName.d.ts +1 -0
  301. package/esm/domain/profiling/utils/getDefaultViewName.js +11 -0
  302. package/esm/domain/profiling/utils/getDefaultViewName.js.map +1 -0
  303. package/esm/domain/profiling/utils/getNumberOfSamples.d.ts +7 -0
  304. package/esm/domain/profiling/utils/getNumberOfSamples.js +15 -0
  305. package/esm/domain/profiling/utils/getNumberOfSamples.js.map +1 -0
  306. package/esm/domain/record/assembly.d.ts +2 -0
  307. package/esm/domain/record/assembly.js +13 -0
  308. package/esm/domain/record/assembly.js.map +1 -0
  309. package/esm/domain/record/elementsScrollPositions.d.ts +10 -0
  310. package/esm/domain/record/elementsScrollPositions.js +20 -0
  311. package/esm/domain/record/elementsScrollPositions.js.map +1 -0
  312. package/esm/domain/record/eventIds.d.ts +4 -0
  313. package/esm/domain/record/eventIds.js +13 -0
  314. package/esm/domain/record/eventIds.js.map +1 -0
  315. package/esm/domain/record/eventsUtils.d.ts +2 -0
  316. package/esm/domain/record/eventsUtils.js +11 -0
  317. package/esm/domain/record/eventsUtils.js.map +1 -0
  318. package/esm/domain/record/index.d.ts +7 -0
  319. package/esm/domain/record/index.js +6 -0
  320. package/esm/domain/record/index.js.map +1 -0
  321. package/esm/domain/record/internalApi.d.ts +22 -0
  322. package/esm/domain/record/internalApi.js +53 -0
  323. package/esm/domain/record/internalApi.js.map +1 -0
  324. package/esm/domain/record/mutationBatch.d.ts +12 -0
  325. package/esm/domain/record/mutationBatch.js +40 -0
  326. package/esm/domain/record/mutationBatch.js.map +1 -0
  327. package/esm/domain/record/nodeIds.d.ts +15 -0
  328. package/esm/domain/record/nodeIds.js +29 -0
  329. package/esm/domain/record/nodeIds.js.map +1 -0
  330. package/esm/domain/record/record.d.ts +16 -0
  331. package/esm/domain/record/record.js +54 -0
  332. package/esm/domain/record/record.js.map +1 -0
  333. package/esm/domain/record/record.types.d.ts +4 -0
  334. package/esm/domain/record/record.types.js +2 -0
  335. package/esm/domain/record/record.types.js.map +1 -0
  336. package/esm/domain/record/recordingScope.d.ts +19 -0
  337. package/esm/domain/record/recordingScope.js +10 -0
  338. package/esm/domain/record/recordingScope.js.map +1 -0
  339. package/esm/domain/record/serialization/index.d.ts +8 -0
  340. package/esm/domain/record/serialization/index.js +7 -0
  341. package/esm/domain/record/serialization/index.js.map +1 -0
  342. package/esm/domain/record/serialization/serialization.types.d.ts +28 -0
  343. package/esm/domain/record/serialization/serialization.types.js +2 -0
  344. package/esm/domain/record/serialization/serialization.types.js.map +1 -0
  345. package/esm/domain/record/serialization/serializationStats.d.ts +12 -0
  346. package/esm/domain/record/serialization/serializationStats.js +27 -0
  347. package/esm/domain/record/serialization/serializationStats.js.map +1 -0
  348. package/esm/domain/record/serialization/serializationTransaction.d.ts +45 -0
  349. package/esm/domain/record/serialization/serializationTransaction.js +35 -0
  350. package/esm/domain/record/serialization/serializationTransaction.js.map +1 -0
  351. package/esm/domain/record/serialization/serializationUtils.d.ts +18 -0
  352. package/esm/domain/record/serialization/serializationUtils.js +80 -0
  353. package/esm/domain/record/serialization/serializationUtils.js.map +1 -0
  354. package/esm/domain/record/serialization/serializeAttribute.d.ts +4 -0
  355. package/esm/domain/record/serialization/serializeAttribute.js +38 -0
  356. package/esm/domain/record/serialization/serializeAttribute.js.map +1 -0
  357. package/esm/domain/record/serialization/serializeAttributes.d.ts +7 -0
  358. package/esm/domain/record/serialization/serializeAttributes.js +161 -0
  359. package/esm/domain/record/serialization/serializeAttributes.js.map +1 -0
  360. package/esm/domain/record/serialization/serializeDocument.d.ts +3 -0
  361. package/esm/domain/record/serialization/serializeDocument.js +8 -0
  362. package/esm/domain/record/serialization/serializeDocument.js.map +1 -0
  363. package/esm/domain/record/serialization/serializeNode.d.ts +7 -0
  364. package/esm/domain/record/serialization/serializeNode.js +149 -0
  365. package/esm/domain/record/serialization/serializeNode.js.map +1 -0
  366. package/esm/domain/record/serialization/serializeStyleSheets.d.ts +2 -0
  367. package/esm/domain/record/serialization/serializeStyleSheets.js +16 -0
  368. package/esm/domain/record/serialization/serializeStyleSheets.js.map +1 -0
  369. package/esm/domain/record/shadowRootsController.d.ts +11 -0
  370. package/esm/domain/record/shadowRootsController.js +41 -0
  371. package/esm/domain/record/shadowRootsController.js.map +1 -0
  372. package/esm/domain/record/startFullSnapshots.d.ts +9 -0
  373. package/esm/domain/record/startFullSnapshots.js +55 -0
  374. package/esm/domain/record/startFullSnapshots.js.map +1 -0
  375. package/esm/domain/record/trackers/index.d.ts +12 -0
  376. package/esm/domain/record/trackers/index.js +12 -0
  377. package/esm/domain/record/trackers/index.js.map +1 -0
  378. package/esm/domain/record/trackers/trackFocus.d.ts +5 -0
  379. package/esm/domain/record/trackers/trackFocus.js +12 -0
  380. package/esm/domain/record/trackers/trackFocus.js.map +1 -0
  381. package/esm/domain/record/trackers/trackFrustration.d.ts +7 -0
  382. package/esm/domain/record/trackers/trackFrustration.js +28 -0
  383. package/esm/domain/record/trackers/trackFrustration.js.map +1 -0
  384. package/esm/domain/record/trackers/trackInput.d.ts +4 -0
  385. package/esm/domain/record/trackers/trackInput.js +101 -0
  386. package/esm/domain/record/trackers/trackInput.js.map +1 -0
  387. package/esm/domain/record/trackers/trackMediaInteraction.d.ts +5 -0
  388. package/esm/domain/record/trackers/trackMediaInteraction.js +26 -0
  389. package/esm/domain/record/trackers/trackMediaInteraction.js.map +1 -0
  390. package/esm/domain/record/trackers/trackMouseInteraction.d.ts +5 -0
  391. package/esm/domain/record/trackers/trackMouseInteraction.js +56 -0
  392. package/esm/domain/record/trackers/trackMouseInteraction.js.map +1 -0
  393. package/esm/domain/record/trackers/trackMove.d.ts +9 -0
  394. package/esm/domain/record/trackers/trackMove.js +51 -0
  395. package/esm/domain/record/trackers/trackMove.js.map +1 -0
  396. package/esm/domain/record/trackers/trackMutation.d.ts +11 -0
  397. package/esm/domain/record/trackers/trackMutation.js +266 -0
  398. package/esm/domain/record/trackers/trackMutation.js.map +1 -0
  399. package/esm/domain/record/trackers/trackScroll.d.ts +5 -0
  400. package/esm/domain/record/trackers/trackScroll.js +45 -0
  401. package/esm/domain/record/trackers/trackScroll.js.map +1 -0
  402. package/esm/domain/record/trackers/trackStyleSheet.d.ts +6 -0
  403. package/esm/domain/record/trackers/trackStyleSheet.js +85 -0
  404. package/esm/domain/record/trackers/trackStyleSheet.js.map +1 -0
  405. package/esm/domain/record/trackers/trackViewEnd.d.ts +5 -0
  406. package/esm/domain/record/trackers/trackViewEnd.js +17 -0
  407. package/esm/domain/record/trackers/trackViewEnd.js.map +1 -0
  408. package/esm/domain/record/trackers/trackViewportResize.d.ts +6 -0
  409. package/esm/domain/record/trackers/trackViewportResize.js +42 -0
  410. package/esm/domain/record/trackers/trackViewportResize.js.map +1 -0
  411. package/esm/domain/record/trackers/tracker.types.d.ts +3 -0
  412. package/esm/domain/record/trackers/tracker.types.js +2 -0
  413. package/esm/domain/record/trackers/tracker.types.js.map +1 -0
  414. package/esm/domain/record/viewports.d.ts +20 -0
  415. package/esm/domain/record/viewports.js +55 -0
  416. package/esm/domain/record/viewports.js.map +1 -0
  417. package/esm/domain/replayStats.d.ts +8 -0
  418. package/esm/domain/replayStats.js +51 -0
  419. package/esm/domain/replayStats.js.map +1 -0
  420. package/esm/domain/scriptLoadingError.d.ts +6 -0
  421. package/esm/domain/scriptLoadingError.js +23 -0
  422. package/esm/domain/scriptLoadingError.js.map +1 -0
  423. package/esm/domain/segmentCollection/buildReplayPayload.d.ts +15 -0
  424. package/esm/domain/segmentCollection/buildReplayPayload.js +23 -0
  425. package/esm/domain/segmentCollection/buildReplayPayload.js.map +1 -0
  426. package/esm/domain/segmentCollection/index.d.ts +4 -0
  427. package/esm/domain/segmentCollection/index.js +4 -0
  428. package/esm/domain/segmentCollection/index.js.map +1 -0
  429. package/esm/domain/segmentCollection/segment.d.ts +16 -0
  430. package/esm/domain/segmentCollection/segment.js +46 -0
  431. package/esm/domain/segmentCollection/segment.js.map +1 -0
  432. package/esm/domain/segmentCollection/segmentCollection.d.ts +31 -0
  433. package/esm/domain/segmentCollection/segmentCollection.js +106 -0
  434. package/esm/domain/segmentCollection/segmentCollection.js.map +1 -0
  435. package/esm/domain/segmentCollection/startSegmentTelemetry.d.ts +6 -0
  436. package/esm/domain/segmentCollection/startSegmentTelemetry.js +44 -0
  437. package/esm/domain/segmentCollection/startSegmentTelemetry.js.map +1 -0
  438. package/esm/domain/startRecordBridge.d.ts +5 -0
  439. package/esm/domain/startRecordBridge.js +14 -0
  440. package/esm/domain/startRecordBridge.js.map +1 -0
  441. package/esm/domain/startRecorderInitTelemetry.d.ts +15 -0
  442. package/esm/domain/startRecorderInitTelemetry.js +52 -0
  443. package/esm/domain/startRecorderInitTelemetry.js.map +1 -0
  444. package/esm/entries/internal.d.ts +11 -0
  445. package/esm/entries/internal.js +4 -0
  446. package/esm/entries/internal.js.map +1 -0
  447. package/esm/entries/internalSynthetics.d.ts +2 -0
  448. package/esm/entries/internalSynthetics.js +23 -0
  449. package/esm/entries/internalSynthetics.js.map +1 -0
  450. package/esm/entries/main.d.ts +23 -0
  451. package/esm/entries/main.js +31 -0
  452. package/esm/entries/main.js.map +1 -0
  453. package/esm/types/index.d.ts +2 -0
  454. package/esm/types/index.js +2 -0
  455. package/esm/types/index.js.map +1 -0
  456. package/esm/types/sessionReplay.d.ts +703 -0
  457. package/esm/types/sessionReplay.js +6 -0
  458. package/esm/types/sessionReplay.js.map +1 -0
  459. package/esm/types/sessionReplayConstants.d.ts +49 -0
  460. package/esm/types/sessionReplayConstants.js +46 -0
  461. package/esm/types/sessionReplayConstants.js.map +1 -0
  462. package/internal/package.json +6 -0
  463. package/internal-synthetics/package.json +6 -0
  464. package/package.json +40 -0
  465. package/src/boot/isBrowserSupported.ts +14 -0
  466. package/src/boot/lazyLoadProfiler.ts +21 -0
  467. package/src/boot/lazyLoadRecorder.ts +21 -0
  468. package/src/boot/postStartStrategy.ts +176 -0
  469. package/src/boot/preStartStrategy.ts +34 -0
  470. package/src/boot/profilerApi.ts +86 -0
  471. package/src/boot/recorderApi.ts +124 -0
  472. package/src/boot/startRecording.ts +70 -0
  473. package/src/domain/deflate/deflateEncoder.ts +144 -0
  474. package/src/domain/deflate/deflateWorker.ts +157 -0
  475. package/src/domain/deflate/index.ts +8 -0
  476. package/src/domain/getSessionReplayLink.ts +40 -0
  477. package/src/domain/profiling/profiler.ts +338 -0
  478. package/src/domain/profiling/profilingContext.ts +34 -0
  479. package/src/domain/profiling/profilingSupported.ts +10 -0
  480. package/src/domain/profiling/test-utils/mockedTrace.ts +58 -0
  481. package/src/domain/profiling/transport/assembly.ts +78 -0
  482. package/src/domain/profiling/transport/buildProfileEventAttributes.ts +66 -0
  483. package/src/domain/profiling/types/index.ts +2 -0
  484. package/src/domain/profiling/types/profilerApi.types.ts +87 -0
  485. package/src/domain/profiling/types/rumProfiler.types.ts +81 -0
  486. package/src/domain/profiling/utils/getCustomOrDefaultViewName.ts +4 -0
  487. package/src/domain/profiling/utils/getDefaultViewName.ts +12 -0
  488. package/src/domain/profiling/utils/getNumberOfSamples.ts +16 -0
  489. package/src/domain/record/assembly.ts +17 -0
  490. package/src/domain/record/elementsScrollPositions.ts +28 -0
  491. package/src/domain/record/eventIds.ts +17 -0
  492. package/src/domain/record/eventsUtils.ts +12 -0
  493. package/src/domain/record/index.ts +7 -0
  494. package/src/domain/record/internalApi.ts +88 -0
  495. package/src/domain/record/mutationBatch.ts +47 -0
  496. package/src/domain/record/nodeIds.ts +46 -0
  497. package/src/domain/record/record.ts +98 -0
  498. package/src/domain/record/record.types.ts +5 -0
  499. package/src/domain/record/recordingScope.ts +36 -0
  500. package/src/domain/record/serialization/index.ts +8 -0
  501. package/src/domain/record/serialization/serialization.types.ts +43 -0
  502. package/src/domain/record/serialization/serializationStats.ts +43 -0
  503. package/src/domain/record/serialization/serializationTransaction.ts +94 -0
  504. package/src/domain/record/serialization/serializationUtils.ts +103 -0
  505. package/src/domain/record/serialization/serializeAttribute.ts +55 -0
  506. package/src/domain/record/serialization/serializeAttributes.ts +194 -0
  507. package/src/domain/record/serialization/serializeDocument.ts +13 -0
  508. package/src/domain/record/serialization/serializeNode.ts +229 -0
  509. package/src/domain/record/serialization/serializeStyleSheets.ts +18 -0
  510. package/src/domain/record/shadowRootsController.ts +62 -0
  511. package/src/domain/record/startFullSnapshots.ts +84 -0
  512. package/src/domain/record/trackers/index.ts +12 -0
  513. package/src/domain/record/trackers/trackFocus.ts +16 -0
  514. package/src/domain/record/trackers/trackFrustration.ts +41 -0
  515. package/src/domain/record/trackers/trackInput.ts +128 -0
  516. package/src/domain/record/trackers/trackMediaInteraction.ts +43 -0
  517. package/src/domain/record/trackers/trackMouseInteraction.ts +74 -0
  518. package/src/domain/record/trackers/trackMove.ts +78 -0
  519. package/src/domain/record/trackers/trackMutation.ts +399 -0
  520. package/src/domain/record/trackers/trackScroll.ts +61 -0
  521. package/src/domain/record/trackers/trackStyleSheet.ts +117 -0
  522. package/src/domain/record/trackers/trackViewEnd.ts +27 -0
  523. package/src/domain/record/trackers/trackViewportResize.ts +69 -0
  524. package/src/domain/record/trackers/tracker.types.ts +3 -0
  525. package/src/domain/record/viewports.ts +68 -0
  526. package/src/domain/replayStats.ts +61 -0
  527. package/src/domain/scriptLoadingError.ts +36 -0
  528. package/src/domain/segmentCollection/buildReplayPayload.ts +52 -0
  529. package/src/domain/segmentCollection/index.ts +4 -0
  530. package/src/domain/segmentCollection/segment.ts +78 -0
  531. package/src/domain/segmentCollection/segmentCollection.ts +200 -0
  532. package/src/domain/segmentCollection/startSegmentTelemetry.ts +82 -0
  533. package/src/domain/startRecordBridge.ts +17 -0
  534. package/src/domain/startRecorderInitTelemetry.ts +90 -0
  535. package/src/entries/internal.ts +18 -0
  536. package/src/entries/internalSynthetics.ts +24 -0
  537. package/src/entries/main.ts +95 -0
  538. package/src/types/index.ts +2 -0
  539. package/src/types/sessionReplay.ts +734 -0
  540. package/src/types/sessionReplayConstants.ts +86 -0
@@ -0,0 +1,94 @@
1
+ import { elapsed, timeStampNow } from '@kubesense/kubesense-browser-core'
2
+
3
+ import type { BrowserRecord } from '../../../types'
4
+ import type { NodeId } from '../nodeIds'
5
+ import type { EmitRecordCallback, EmitStatsCallback } from '../record.types'
6
+ import type { RecordingScope } from '../recordingScope'
7
+ import type { SerializationStats } from './serializationStats'
8
+ import { createSerializationStats, updateSerializationStats } from './serializationStats'
9
+
10
+ export type SerializationTransactionCallback = (transaction: SerializationTransaction) => void
11
+
12
+ export const enum SerializationKind {
13
+ INITIAL_FULL_SNAPSHOT,
14
+ SUBSEQUENT_FULL_SNAPSHOT,
15
+ INCREMENTAL_SNAPSHOT,
16
+ }
17
+
18
+ /**
19
+ * A serialization transaction is used to build and emit a sequence of session replay
20
+ * records containing a serialized snapshot of the DOM.
21
+ */
22
+ export interface SerializationTransaction {
23
+ /** Add a record to the transaction. It will be emitted when the transaction ends. */
24
+ add(record: BrowserRecord): void
25
+
26
+ /**
27
+ * Add a metric to the transaction's statistics. The aggregated statistics will be
28
+ * emitted when the transaction ends.
29
+ */
30
+ addMetric(metric: keyof SerializationStats, value: number): void
31
+
32
+ /**
33
+ * Assign and return an id to the given node. If the node has previously been assigned
34
+ * an id, the existing id will be reused.
35
+ */
36
+ assignId(node: Node): NodeId
37
+
38
+ /** The kind of serialization being performed in this transaction. */
39
+ kind: SerializationKind
40
+
41
+ /**
42
+ * A set used to track nodes which have been serialized in the current transaction. If
43
+ * undefined, this feature is disabled; this is the default state in new transactions
44
+ * for performance reasons. Set the property to a non-undefined value if you need this
45
+ * capability.
46
+ */
47
+ serializedNodeIds?: Set<NodeId>
48
+
49
+ /** The recording scope in which this transaction is occurring. */
50
+ scope: RecordingScope
51
+ }
52
+
53
+ /**
54
+ * Perform serialization within a transaction. At the end of the transaction, the
55
+ * generated records and statistics will be emitted.
56
+ */
57
+ export function serializeInTransaction(
58
+ kind: SerializationKind,
59
+ emitRecord: EmitRecordCallback,
60
+ emitStats: EmitStatsCallback,
61
+ scope: RecordingScope,
62
+ serialize: SerializationTransactionCallback
63
+ ): void {
64
+ const records: BrowserRecord[] = []
65
+ const stats = createSerializationStats()
66
+
67
+ const transaction: SerializationTransaction = {
68
+ add(record: BrowserRecord): void {
69
+ records.push(record)
70
+ },
71
+ addMetric(metric: keyof SerializationStats, value: number): void {
72
+ updateSerializationStats(stats, metric, value)
73
+ },
74
+ assignId(node: Node): NodeId {
75
+ const id = scope.nodeIds.assign(node)
76
+ if (transaction.serializedNodeIds) {
77
+ transaction.serializedNodeIds.add(id)
78
+ }
79
+ return id
80
+ },
81
+ kind,
82
+ scope,
83
+ }
84
+
85
+ const start = timeStampNow()
86
+ serialize(transaction)
87
+ updateSerializationStats(stats, 'serializationDuration', elapsed(start, timeStampNow()))
88
+
89
+ for (const record of records) {
90
+ emitRecord(record)
91
+ }
92
+
93
+ emitStats(stats)
94
+ }
@@ -0,0 +1,103 @@
1
+ import { buildUrl } from '@kubesense/kubesense-browser-core'
2
+ import { CENSORED_STRING_MARK, shouldMaskNode } from '@kubesense/kubesense-browser-rum-core'
3
+ import type { NodePrivacyLevel } from '@kubesense/kubesense-browser-rum-core'
4
+
5
+ /**
6
+ * Get the element "value" to be serialized as an attribute or an input update record. It respects
7
+ * the input privacy mode of the element.
8
+ * PERFROMANCE OPTIMIZATION: Assumes that privacy level `HIDDEN` is never encountered because of earlier checks.
9
+ */
10
+ export function getElementInputValue(element: Element, nodePrivacyLevel: NodePrivacyLevel) {
11
+ /*
12
+ BROWSER SPEC NOTE: <input>, <select>
13
+ For some <input> elements, the `value` is an exceptional property/attribute that has the
14
+ value synced between el.value and el.getAttribute()
15
+ input[type=button,checkbox,hidden,image,radio,reset,submit]
16
+ */
17
+ const tagName = element.tagName
18
+ const value = (element as HTMLInputElement | HTMLTextAreaElement).value
19
+
20
+ if (shouldMaskNode(element, nodePrivacyLevel)) {
21
+ const type = (element as HTMLInputElement | HTMLTextAreaElement).type
22
+ if (tagName === 'INPUT' && (type === 'button' || type === 'submit' || type === 'reset')) {
23
+ // Overrule `MASK` privacy level for button-like element values, as they are used during replay
24
+ // to display their label. They can still be hidden via the "hidden" privacy attribute or class name.
25
+ return value
26
+ } else if (!value || tagName === 'OPTION') {
27
+ // <Option> value provides no benefit
28
+ return
29
+ }
30
+ return CENSORED_STRING_MARK
31
+ }
32
+
33
+ if (tagName === 'OPTION' || tagName === 'SELECT') {
34
+ return (element as HTMLOptionElement | HTMLSelectElement).value
35
+ }
36
+
37
+ if (tagName !== 'INPUT' && tagName !== 'TEXTAREA') {
38
+ return
39
+ }
40
+
41
+ return value
42
+ }
43
+
44
+ export const URL_IN_CSS_REF = /url\((?:(')([^']*)'|(")([^"]*)"|([^)]*))\)/gm
45
+ export const ABSOLUTE_URL = /^[A-Za-z]+:|^\/\//
46
+ export const DATA_URI = /^["']?data:.*,/i
47
+
48
+ export function switchToAbsoluteUrl(cssText: string, cssHref: string | null): string {
49
+ return cssText.replace(
50
+ URL_IN_CSS_REF,
51
+ (
52
+ matchingSubstring: string,
53
+ singleQuote: string | undefined,
54
+ urlWrappedInSingleQuotes: string | undefined,
55
+ doubleQuote: string | undefined,
56
+ urlWrappedInDoubleQuotes: string | undefined,
57
+ urlNotWrappedInQuotes: string | undefined
58
+ ) => {
59
+ const url = urlWrappedInSingleQuotes || urlWrappedInDoubleQuotes || urlNotWrappedInQuotes
60
+
61
+ if (!cssHref || !url || ABSOLUTE_URL.test(url) || DATA_URI.test(url)) {
62
+ return matchingSubstring
63
+ }
64
+
65
+ const quote = singleQuote || doubleQuote || ''
66
+ return `url(${quote}${makeUrlAbsolute(url, cssHref)}${quote})`
67
+ }
68
+ )
69
+ }
70
+
71
+ function makeUrlAbsolute(url: string, baseUrl: string): string {
72
+ try {
73
+ return buildUrl(url, baseUrl).href
74
+ } catch {
75
+ return url
76
+ }
77
+ }
78
+
79
+ const TAG_NAME_REGEX = /[^a-z1-6-_]/
80
+ export function getValidTagName(tagName: string): string {
81
+ const processedTagName = tagName.toLowerCase().trim()
82
+
83
+ if (TAG_NAME_REGEX.test(processedTagName)) {
84
+ // if the tag name is odd and we cannot extract
85
+ // anything from the string, then we return a
86
+ // generic div
87
+ return 'div'
88
+ }
89
+
90
+ return processedTagName
91
+ }
92
+
93
+ /**
94
+ * Returns the tag name of the given element, normalized to ensure a consistent lowercase
95
+ * representation regardless of whether the element is HTML, XHTML, or SVG.
96
+ */
97
+ export function normalizedTagName(element: Element): string {
98
+ return element.tagName.toLowerCase()
99
+ }
100
+
101
+ export function censoredImageForSize(width: number, height: number) {
102
+ return `data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='${width}' height='${height}' style='background-color:silver'%3E%3C/svg%3E`
103
+ }
@@ -0,0 +1,55 @@
1
+ import {
2
+ NodePrivacyLevel,
3
+ CENSORED_STRING_MARK,
4
+ CENSORED_IMG_MARK,
5
+ sanitizeIfLongDataUrl,
6
+ shouldMaskAttribute,
7
+ } from '@kubesense/kubesense-browser-rum-core'
8
+ import type { RumConfiguration } from '@kubesense/kubesense-browser-rum-core'
9
+ import { censoredImageForSize } from './serializationUtils'
10
+
11
+ // TODO: temporarily bump the Session Replay limit to 1Mb for dataUrls
12
+ // This limit should be removed after [PANA-2843] is implemented
13
+ export const MAX_ATTRIBUTE_VALUE_CHAR_LENGTH = 1_000_000
14
+
15
+ export function serializeAttribute(
16
+ element: Element,
17
+ nodePrivacyLevel: NodePrivacyLevel,
18
+ attributeName: string,
19
+ configuration: RumConfiguration
20
+ ): string | null {
21
+ if (nodePrivacyLevel === NodePrivacyLevel.HIDDEN) {
22
+ // dup condition for direct access case
23
+ return null
24
+ }
25
+
26
+ const attributeValue = element.getAttribute(attributeName)
27
+ const tagName = element.tagName
28
+ if (shouldMaskAttribute(tagName, attributeName, attributeValue, nodePrivacyLevel, configuration)) {
29
+ // mask image URLs
30
+ if (tagName === 'IMG') {
31
+ // generate image with similar dimension than the original to have the same rendering behaviour
32
+ const image = element as HTMLImageElement
33
+ if (image.naturalWidth > 0) {
34
+ return censoredImageForSize(image.naturalWidth, image.naturalHeight)
35
+ }
36
+ const { width, height } = element.getBoundingClientRect()
37
+ if (width > 0 || height > 0) {
38
+ return censoredImageForSize(width, height)
39
+ }
40
+ // if we can't get the image size, fallback to the censored image
41
+ return CENSORED_IMG_MARK
42
+ }
43
+ if (tagName === 'SOURCE') {
44
+ return CENSORED_IMG_MARK
45
+ }
46
+
47
+ return CENSORED_STRING_MARK
48
+ }
49
+
50
+ if (!attributeValue) {
51
+ return attributeValue
52
+ }
53
+
54
+ return sanitizeIfLongDataUrl(attributeValue, MAX_ATTRIBUTE_VALUE_CHAR_LENGTH)
55
+ }
@@ -0,0 +1,194 @@
1
+ import { NodePrivacyLevel, shouldMaskNode } from '@kubesense/kubesense-browser-rum-core'
2
+ import { isSafari } from '@kubesense/kubesense-browser-core'
3
+ import { getElementInputValue, normalizedTagName, switchToAbsoluteUrl } from './serializationUtils'
4
+ import { serializeAttribute } from './serializeAttribute'
5
+ import type { SerializationTransaction } from './serializationTransaction'
6
+ import { SerializationKind } from './serializationTransaction'
7
+ import type { VirtualAttributes } from './serialization.types'
8
+
9
+ export function serializeAttributes(
10
+ element: Element,
11
+ nodePrivacyLevel: NodePrivacyLevel,
12
+ transaction: SerializationTransaction
13
+ ): Record<string, number | string> {
14
+ return {
15
+ ...serializeDOMAttributes(element, nodePrivacyLevel, transaction),
16
+ ...serializeVirtualAttributes(element, nodePrivacyLevel, transaction),
17
+ }
18
+ }
19
+
20
+ export function serializeDOMAttributes(
21
+ element: Element,
22
+ nodePrivacyLevel: NodePrivacyLevel,
23
+ transaction: SerializationTransaction
24
+ ): Record<string, string> {
25
+ if (nodePrivacyLevel === NodePrivacyLevel.HIDDEN) {
26
+ return {}
27
+ }
28
+
29
+ const attrs: Record<string, string> = {}
30
+ const tagName = normalizedTagName(element)
31
+
32
+ for (let i = 0; i < element.attributes.length; i += 1) {
33
+ const attribute = element.attributes.item(i)!
34
+ const attributeName = attribute.name
35
+ const attributeValue = serializeAttribute(element, nodePrivacyLevel, attributeName, transaction.scope.configuration)
36
+ if (attributeValue !== null) {
37
+ attrs[attributeName] = attributeValue
38
+ }
39
+ }
40
+
41
+ if (
42
+ (element as HTMLInputElement).value &&
43
+ (tagName === 'textarea' || tagName === 'select' || tagName === 'option' || tagName === 'input')
44
+ ) {
45
+ const formValue = getElementInputValue(element, nodePrivacyLevel)
46
+ if (formValue !== undefined) {
47
+ attrs.value = formValue
48
+ }
49
+ }
50
+
51
+ /**
52
+ * <Option> can be selected, which occurs if its `value` matches ancestor `<Select>.value`
53
+ */
54
+ if (tagName === 'option') {
55
+ const optionElement = element as HTMLOptionElement
56
+ if (optionElement.selected && !shouldMaskNode(optionElement, nodePrivacyLevel)) {
57
+ attrs.selected = ''
58
+ } else {
59
+ delete attrs.selected
60
+ }
61
+ }
62
+
63
+ /**
64
+ * Forms: input[type=checkbox,radio]
65
+ * The `checked` property for <input> is a little bit special:
66
+ * 1. el.checked is a setter that returns if truthy.
67
+ * 2. getAttribute returns the string value
68
+ * getAttribute('checked') does not sync with `Element.checked`, so use JS property
69
+ * NOTE: `checked` property exists on `HTMLInputElement`. For serializer assumptions, we check for type=radio|check.
70
+ */
71
+ const inputElement = element as HTMLInputElement
72
+ if (tagName === 'input' && (inputElement.type === 'radio' || inputElement.type === 'checkbox')) {
73
+ if (inputElement.checked && !shouldMaskNode(inputElement, nodePrivacyLevel)) {
74
+ attrs.checked = ''
75
+ } else {
76
+ delete attrs.checked
77
+ }
78
+ }
79
+
80
+ return attrs
81
+ }
82
+
83
+ export function serializeVirtualAttributes(
84
+ element: Element,
85
+ nodePrivacyLevel: NodePrivacyLevel,
86
+ transaction: SerializationTransaction
87
+ ): VirtualAttributes {
88
+ if (nodePrivacyLevel === NodePrivacyLevel.HIDDEN) {
89
+ return {}
90
+ }
91
+
92
+ const attrs: VirtualAttributes = {}
93
+ const doc = element.ownerDocument
94
+ const tagName = normalizedTagName(element)
95
+
96
+ // remote css
97
+ if (tagName === 'link') {
98
+ const stylesheet = Array.from(doc.styleSheets).find((s) => s.href === (element as HTMLLinkElement).href)
99
+ const cssText = getCssRulesString(stylesheet)
100
+ if (cssText && stylesheet) {
101
+ transaction.addMetric('cssText', cssText.length)
102
+ attrs._cssText = cssText
103
+ }
104
+ }
105
+
106
+ // dynamic stylesheet
107
+ if (tagName === 'style' && (element as HTMLStyleElement).sheet) {
108
+ const cssText = getCssRulesString((element as HTMLStyleElement).sheet)
109
+ if (cssText) {
110
+ transaction.addMetric('cssText', cssText.length)
111
+ attrs._cssText = cssText
112
+ }
113
+ }
114
+
115
+ /**
116
+ * Serialize the media playback state
117
+ */
118
+ if (tagName === 'audio' || tagName === 'video') {
119
+ const mediaElement = element as HTMLMediaElement
120
+ attrs.rr_mediaState = mediaElement.paused ? 'paused' : 'played'
121
+ }
122
+
123
+ /**
124
+ * Serialize the scroll state for each element only for full snapshot
125
+ */
126
+ let scrollTop: number | undefined
127
+ let scrollLeft: number | undefined
128
+ switch (transaction.kind) {
129
+ case SerializationKind.INITIAL_FULL_SNAPSHOT:
130
+ scrollTop = Math.round(element.scrollTop)
131
+ scrollLeft = Math.round(element.scrollLeft)
132
+ if (scrollTop || scrollLeft) {
133
+ transaction.scope.elementsScrollPositions.set(element, { scrollTop, scrollLeft })
134
+ }
135
+ break
136
+ case SerializationKind.SUBSEQUENT_FULL_SNAPSHOT:
137
+ if (transaction.scope.elementsScrollPositions.has(element)) {
138
+ ;({ scrollTop, scrollLeft } = transaction.scope.elementsScrollPositions.get(element)!)
139
+ }
140
+ break
141
+ }
142
+ if (scrollLeft) {
143
+ attrs.rr_scrollLeft = scrollLeft
144
+ }
145
+ if (scrollTop) {
146
+ attrs.rr_scrollTop = scrollTop
147
+ }
148
+
149
+ return attrs
150
+ }
151
+
152
+ export function getCssRulesString(cssStyleSheet: CSSStyleSheet | undefined | null): string | null {
153
+ if (!cssStyleSheet) {
154
+ return null
155
+ }
156
+ let rules: CSSRuleList | undefined
157
+ try {
158
+ rules = cssStyleSheet.rules || cssStyleSheet.cssRules
159
+ } catch {
160
+ // if css is protected by CORS we cannot access cssRules see: https://www.w3.org/TR/cssom-1/#the-cssstylesheet-interface
161
+ }
162
+ if (!rules) {
163
+ return null
164
+ }
165
+ const styleSheetCssText = Array.from(rules, isSafari() ? getCssRuleStringForSafari : getCssRuleString).join('')
166
+ return switchToAbsoluteUrl(styleSheetCssText, cssStyleSheet.href)
167
+ }
168
+
169
+ function getCssRuleStringForSafari(rule: CSSRule): string {
170
+ // Safari does not escape attribute selectors containing : properly
171
+ // https://bugs.webkit.org/show_bug.cgi?id=184604
172
+ if (isCSSStyleRule(rule) && rule.selectorText.includes(':')) {
173
+ // This regex replaces [foo:bar] by [foo\\:bar]
174
+ const escapeColon = /(\[[\w-]+[^\\])(:[^\]]+\])/g
175
+ return rule.cssText.replace(escapeColon, '$1\\$2')
176
+ }
177
+
178
+ return getCssRuleString(rule)
179
+ }
180
+
181
+ function getCssRuleString(rule: CSSRule): string {
182
+ // If it's an @import rule, try to inline sub-rules recursively with `getCssRulesString`. This
183
+ // operation can fail if the imported stylesheet is protected by CORS, in which case we fallback
184
+ // to the @import rule CSS text.
185
+ return (isCSSImportRule(rule) && getCssRulesString(rule.styleSheet)) || rule.cssText
186
+ }
187
+
188
+ function isCSSImportRule(rule: CSSRule): rule is CSSImportRule {
189
+ return 'styleSheet' in rule
190
+ }
191
+
192
+ function isCSSStyleRule(rule: CSSRule): rule is CSSStyleRule {
193
+ return 'selectorText' in rule
194
+ }
@@ -0,0 +1,13 @@
1
+ import type { DocumentNode, SerializedNodeWithId } from '../../../types'
2
+ import { serializeNode } from './serializeNode'
3
+ import type { SerializationTransaction } from './serializationTransaction'
4
+
5
+ export function serializeDocument(
6
+ document: Document,
7
+ transaction: SerializationTransaction
8
+ ): DocumentNode & SerializedNodeWithId {
9
+ const defaultPrivacyLevel = transaction.scope.configuration.defaultPrivacyLevel
10
+ const serializedNode = serializeNode(document, defaultPrivacyLevel, transaction)
11
+ // We are sure that Documents are never ignored, so this function never returns null
12
+ return serializedNode as DocumentNode & SerializedNodeWithId
13
+ }
@@ -0,0 +1,229 @@
1
+ import {
2
+ reducePrivacyLevel,
3
+ getNodeSelfPrivacyLevel,
4
+ getTextContent,
5
+ isNodeShadowRoot,
6
+ hasChildNodes,
7
+ forEachChildNodes,
8
+ NodePrivacyLevel,
9
+ PRIVACY_ATTR_NAME,
10
+ PRIVACY_ATTR_VALUE_HIDDEN,
11
+ } from '@kubesense/kubesense-browser-rum-core'
12
+ import type {
13
+ DocumentFragmentNode,
14
+ DocumentNode,
15
+ SerializedNodeWithId,
16
+ CDataNode,
17
+ DocumentTypeNode,
18
+ ElementNode,
19
+ TextNode,
20
+ } from '../../../types'
21
+ import { NodeType } from '../../../types'
22
+ import { getValidTagName } from './serializationUtils'
23
+ import type { ParentNodePrivacyLevel } from './serialization.types'
24
+ import { serializeStyleSheets } from './serializeStyleSheets'
25
+ import { serializeAttributes } from './serializeAttributes'
26
+ import type { SerializationTransaction } from './serializationTransaction'
27
+
28
+ export function serializeNode(
29
+ node: Element,
30
+ parentNodePrivacyLevel: ParentNodePrivacyLevel,
31
+ transaction: SerializationTransaction
32
+ ): (SerializedNodeWithId & ElementNode) | null
33
+ export function serializeNode(
34
+ node: Node,
35
+ parentNodePrivacyLevel: ParentNodePrivacyLevel,
36
+ transaction: SerializationTransaction
37
+ ): SerializedNodeWithId | null
38
+ export function serializeNode(
39
+ node: Node,
40
+ parentNodePrivacyLevel: ParentNodePrivacyLevel,
41
+ transaction: SerializationTransaction
42
+ ): SerializedNodeWithId | null {
43
+ switch (node.nodeType) {
44
+ case node.DOCUMENT_NODE:
45
+ return serializeDocumentNode(node as Document, parentNodePrivacyLevel, transaction)
46
+ case node.DOCUMENT_FRAGMENT_NODE:
47
+ return serializeDocumentFragmentNode(node as DocumentFragment, parentNodePrivacyLevel, transaction)
48
+ case node.DOCUMENT_TYPE_NODE:
49
+ return serializeDocumentTypeNode(node as DocumentType, transaction)
50
+ case node.ELEMENT_NODE:
51
+ return serializeElementNode(node as Element, parentNodePrivacyLevel, transaction)
52
+ case node.TEXT_NODE:
53
+ return serializeTextNode(node as Text, parentNodePrivacyLevel, transaction)
54
+ case node.CDATA_SECTION_NODE:
55
+ return serializeCDataNode(node as CDATASection, transaction)
56
+ default:
57
+ return null
58
+ }
59
+ }
60
+
61
+ export function serializeChildNodes(
62
+ node: Node,
63
+ parentNodePrivacyLevel: ParentNodePrivacyLevel,
64
+ transaction: SerializationTransaction
65
+ ): SerializedNodeWithId[] {
66
+ const result: SerializedNodeWithId[] = []
67
+ forEachChildNodes(node, (childNode) => {
68
+ const serializedChildNode = serializeNode(childNode, parentNodePrivacyLevel, transaction)
69
+ if (serializedChildNode) {
70
+ result.push(serializedChildNode)
71
+ }
72
+ })
73
+ return result
74
+ }
75
+
76
+ export function serializeDocumentNode(
77
+ document: Document,
78
+ parentNodePrivacyLevel: ParentNodePrivacyLevel,
79
+ transaction: SerializationTransaction
80
+ ): DocumentNode & SerializedNodeWithId {
81
+ return {
82
+ type: NodeType.Document,
83
+ id: transaction.assignId(document),
84
+ childNodes: serializeChildNodes(document, parentNodePrivacyLevel, transaction),
85
+ adoptedStyleSheets: serializeStyleSheets(document.adoptedStyleSheets),
86
+ }
87
+ }
88
+
89
+ function serializeDocumentFragmentNode(
90
+ element: DocumentFragment,
91
+ parentNodePrivacyLevel: ParentNodePrivacyLevel,
92
+ transaction: SerializationTransaction
93
+ ): DocumentFragmentNode & SerializedNodeWithId {
94
+ const isShadowRoot = isNodeShadowRoot(element)
95
+ if (isShadowRoot) {
96
+ transaction.scope.shadowRootsController.addShadowRoot(element, transaction.scope)
97
+ }
98
+
99
+ return {
100
+ type: NodeType.DocumentFragment,
101
+ id: transaction.assignId(element),
102
+ childNodes: serializeChildNodes(element, parentNodePrivacyLevel, transaction),
103
+ isShadowRoot,
104
+ adoptedStyleSheets: isShadowRoot ? serializeStyleSheets(element.adoptedStyleSheets) : undefined,
105
+ }
106
+ }
107
+
108
+ function serializeDocumentTypeNode(
109
+ documentType: DocumentType,
110
+ transaction: SerializationTransaction
111
+ ): DocumentTypeNode & SerializedNodeWithId {
112
+ return {
113
+ type: NodeType.DocumentType,
114
+ id: transaction.assignId(documentType),
115
+ name: documentType.name,
116
+ publicId: documentType.publicId,
117
+ systemId: documentType.systemId,
118
+ }
119
+ }
120
+
121
+ /**
122
+ * Serializing Element nodes involves capturing:
123
+ * 1. HTML ATTRIBUTES:
124
+ * 2. JS STATE:
125
+ * - scroll offsets
126
+ * - Form fields (input value, checkbox checked, option selection, range)
127
+ * - Canvas state,
128
+ * - Media (video/audio) play mode + currentTime
129
+ * - iframe contents
130
+ * - webcomponents
131
+ * 3. CUSTOM PROPERTIES:
132
+ * - height+width for when `hidden` to cover the element
133
+ * 4. EXCLUDED INTERACTION STATE:
134
+ * - focus (possible, but not worth perf impact)
135
+ * - hover (tracked only via mouse activity)
136
+ * - fullscreen mode
137
+ */
138
+
139
+ function serializeElementNode(
140
+ element: Element,
141
+ parentNodePrivacyLevel: ParentNodePrivacyLevel,
142
+ transaction: SerializationTransaction
143
+ ): (ElementNode & SerializedNodeWithId) | null {
144
+ const tagName = getValidTagName(element.tagName)
145
+ const isSVG = isSVGElement(element) || undefined
146
+
147
+ // For performance reason, we don't use getNodePrivacyLevel directly: we leverage the
148
+ // parentNodePrivacyLevel option to avoid iterating over all parents
149
+ const nodePrivacyLevel = reducePrivacyLevel(getNodeSelfPrivacyLevel(element), parentNodePrivacyLevel)
150
+
151
+ if (nodePrivacyLevel === NodePrivacyLevel.HIDDEN) {
152
+ const { width, height } = element.getBoundingClientRect()
153
+ return {
154
+ type: NodeType.Element,
155
+ id: transaction.assignId(element),
156
+ tagName,
157
+ attributes: {
158
+ rr_width: `${width}px`,
159
+ rr_height: `${height}px`,
160
+ [PRIVACY_ATTR_NAME]: PRIVACY_ATTR_VALUE_HIDDEN,
161
+ },
162
+ childNodes: [],
163
+ isSVG,
164
+ }
165
+ }
166
+
167
+ // Ignore Elements like Script and some Link, Metas
168
+ if (nodePrivacyLevel === NodePrivacyLevel.IGNORE) {
169
+ return null
170
+ }
171
+
172
+ const id = transaction.assignId(element)
173
+ const attributes = serializeAttributes(element, nodePrivacyLevel, transaction)
174
+
175
+ let childNodes: SerializedNodeWithId[] = []
176
+ if (
177
+ hasChildNodes(element) &&
178
+ // Do not serialize style children as the css rules are already in the _cssText attribute
179
+ tagName !== 'style'
180
+ ) {
181
+ childNodes = serializeChildNodes(element, nodePrivacyLevel, transaction)
182
+ }
183
+
184
+ return {
185
+ type: NodeType.Element,
186
+ id,
187
+ tagName,
188
+ attributes,
189
+ childNodes,
190
+ isSVG,
191
+ }
192
+ }
193
+
194
+ function isSVGElement(el: Element): boolean {
195
+ return el.tagName === 'svg' || el instanceof SVGElement
196
+ }
197
+
198
+ /**
199
+ * Text Nodes are dependant on Element nodes
200
+ * Privacy levels are set on elements so we check the parentElement of a text node
201
+ * for privacy level.
202
+ */
203
+
204
+ function serializeTextNode(
205
+ textNode: Text,
206
+ parentNodePrivacyLevel: ParentNodePrivacyLevel,
207
+ transaction: SerializationTransaction
208
+ ): (TextNode & SerializedNodeWithId) | null {
209
+ const textContent = getTextContent(textNode, parentNodePrivacyLevel)
210
+ if (textContent === undefined) {
211
+ return null
212
+ }
213
+ return {
214
+ type: NodeType.Text,
215
+ id: transaction.assignId(textNode),
216
+ textContent,
217
+ }
218
+ }
219
+
220
+ function serializeCDataNode(
221
+ node: CDATASection,
222
+ transaction: SerializationTransaction
223
+ ): CDataNode & SerializedNodeWithId {
224
+ return {
225
+ type: NodeType.CDATA,
226
+ id: transaction.assignId(node),
227
+ textContent: '',
228
+ }
229
+ }