@ably/ui 17.4.2 → 17.4.3

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 (339) hide show
  1. package/AGENTS.md +573 -0
  2. package/README.md +120 -68
  3. package/core/Accordion/types.js.map +1 -1
  4. package/core/Accordion/utils.js +1 -1
  5. package/core/Accordion/utils.js.map +1 -1
  6. package/core/Accordion.js +1 -1
  7. package/core/Accordion.js.map +1 -1
  8. package/core/Badge.js +1 -1
  9. package/core/Badge.js.map +1 -1
  10. package/core/Code/Code.test.js +2 -0
  11. package/core/Code/Code.test.js.map +1 -0
  12. package/core/Code.js +1 -1
  13. package/core/Code.js.map +1 -1
  14. package/core/CodeSnippet/ApiKeySelector.js +1 -1
  15. package/core/CodeSnippet/ApiKeySelector.js.map +1 -1
  16. package/core/CodeSnippet/CodeSnippet.test.js +2 -0
  17. package/core/CodeSnippet/CodeSnippet.test.js.map +1 -0
  18. package/core/CodeSnippet/CopyButton.js +1 -1
  19. package/core/CodeSnippet/CopyButton.js.map +1 -1
  20. package/core/CodeSnippet/LanguageSelector.js +1 -1
  21. package/core/CodeSnippet/LanguageSelector.js.map +1 -1
  22. package/core/CodeSnippet/PlainCodeView.js +1 -1
  23. package/core/CodeSnippet/PlainCodeView.js.map +1 -1
  24. package/core/CodeSnippet/TooltipButton.js +1 -1
  25. package/core/CodeSnippet/TooltipButton.js.map +1 -1
  26. package/core/CodeSnippet/languages.js +1 -1
  27. package/core/CodeSnippet/languages.js.map +1 -1
  28. package/core/CodeSnippet/languages.test.js +2 -0
  29. package/core/CodeSnippet/languages.test.js.map +1 -0
  30. package/core/CodeSnippet.js +1 -1
  31. package/core/CodeSnippet.js.map +1 -1
  32. package/core/ConnectStateWrapper.js.map +1 -1
  33. package/core/ContentTile.js +2 -0
  34. package/core/ContentTile.js.map +1 -0
  35. package/core/DropdownMenu.js +1 -1
  36. package/core/DropdownMenu.js.map +1 -1
  37. package/core/Expander.js +1 -1
  38. package/core/Expander.js.map +1 -1
  39. package/core/FeaturedLink.js +1 -1
  40. package/core/FeaturedLink.js.map +1 -1
  41. package/core/Flash.js +1 -1
  42. package/core/Flash.js.map +1 -1
  43. package/core/Flyout.js +1 -1
  44. package/core/Flyout.js.map +1 -1
  45. package/core/Footer/data.js +1 -1
  46. package/core/Footer/data.js.map +1 -1
  47. package/core/Footer.js +1 -1
  48. package/core/Footer.js.map +1 -1
  49. package/core/Header/HeaderLinks.js +1 -1
  50. package/core/Header/HeaderLinks.js.map +1 -1
  51. package/core/Header/types.js +2 -0
  52. package/core/Header/types.js.map +1 -0
  53. package/core/Header.js +1 -1
  54. package/core/Header.js.map +1 -1
  55. package/core/Icon/components/icon-display-cloud-servers-mono.js +2 -0
  56. package/core/Icon/components/icon-display-cloud-servers-mono.js.map +1 -0
  57. package/core/Icon/components/icon-display-data-integrity.js +2 -0
  58. package/core/Icon/components/icon-display-data-integrity.js.map +1 -0
  59. package/core/Icon/components/icon-display-database-connector.js +2 -0
  60. package/core/Icon/components/icon-display-database-connector.js.map +1 -0
  61. package/core/Icon/components/icon-display-ephemeral-messages-dark-col.js +2 -0
  62. package/core/Icon/components/icon-display-ephemeral-messages-dark-col.js.map +1 -0
  63. package/core/Icon/components/icon-display-ephemeral-messages.js +2 -0
  64. package/core/Icon/components/icon-display-ephemeral-messages.js.map +1 -0
  65. package/core/Icon/components/icon-display-live-updates.js +2 -0
  66. package/core/Icon/components/icon-display-live-updates.js.map +1 -0
  67. package/core/Icon/components/icon-display-message-annotations-dark-col.js +2 -0
  68. package/core/Icon/components/icon-display-message-annotations-dark-col.js.map +1 -0
  69. package/core/Icon/components/icon-display-message-annotations.js +2 -0
  70. package/core/Icon/components/icon-display-message-annotations.js.map +1 -0
  71. package/core/Icon/components/icon-display-multi-user-spaces.js +2 -0
  72. package/core/Icon/components/icon-display-multi-user-spaces.js.map +1 -0
  73. package/core/Icon/components/icon-display-sdks.js +2 -0
  74. package/core/Icon/components/icon-display-sdks.js.map +1 -0
  75. package/core/Icon/components/icon-display-something-else-mono.js +2 -0
  76. package/core/Icon/components/icon-display-something-else-mono.js.map +1 -0
  77. package/core/Icon/components/icon-display-something-else.js +2 -0
  78. package/core/Icon/components/icon-display-something-else.js.map +1 -0
  79. package/core/Icon/components/icon-display-ui-mono.js +2 -0
  80. package/core/Icon/components/icon-display-ui-mono.js.map +1 -0
  81. package/core/Icon/components/icon-display-ui.js +2 -0
  82. package/core/Icon/components/icon-display-ui.js.map +1 -0
  83. package/core/Icon/components/icon-gui-checklist-checked.js +1 -1
  84. package/core/Icon/components/icon-gui-checklist-checked.js.map +1 -1
  85. package/core/Icon/components/icon-gui-code-doc.js +1 -1
  86. package/core/Icon/components/icon-gui-code-doc.js.map +1 -1
  87. package/core/Icon/components/icon-gui-cursor.js +1 -1
  88. package/core/Icon/components/icon-gui-cursor.js.map +1 -1
  89. package/core/Icon/components/icon-gui-expand.js +1 -1
  90. package/core/Icon/components/icon-gui-expand.js.map +1 -1
  91. package/core/Icon/components/icon-gui-filter-flow-step-0.js +1 -1
  92. package/core/Icon/components/icon-gui-filter-flow-step-0.js.map +1 -1
  93. package/core/Icon/components/icon-gui-flower-growth.js +1 -1
  94. package/core/Icon/components/icon-gui-flower-growth.js.map +1 -1
  95. package/core/Icon/components/icon-gui-glasses.js +1 -1
  96. package/core/Icon/components/icon-gui-glasses.js.map +1 -1
  97. package/core/Icon/components/icon-gui-heartbeat-outline.js +2 -0
  98. package/core/Icon/components/icon-gui-heartbeat-outline.js.map +1 -0
  99. package/core/Icon/components/icon-gui-heartbeat-solid.js +2 -0
  100. package/core/Icon/components/icon-gui-heartbeat-solid.js.map +1 -0
  101. package/core/Icon/components/icon-gui-mouse.js +1 -1
  102. package/core/Icon/components/icon-gui-mouse.js.map +1 -1
  103. package/core/Icon/components/icon-gui-pitfall.js +1 -1
  104. package/core/Icon/components/icon-gui-pitfall.js.map +1 -1
  105. package/core/Icon/components/icon-gui-prod-ai-transport-outline.js +2 -0
  106. package/core/Icon/components/icon-gui-prod-ai-transport-outline.js.map +1 -0
  107. package/core/Icon/components/icon-gui-prod-ai-transport-solid.js +2 -0
  108. package/core/Icon/components/icon-gui-prod-ai-transport-solid.js.map +1 -0
  109. package/core/Icon/components/icon-gui-quote-marks-fill.js +1 -1
  110. package/core/Icon/components/icon-gui-quote-marks-fill.js.map +1 -1
  111. package/core/Icon/components/icon-product-ai-transport-mono.js +2 -0
  112. package/core/Icon/components/icon-product-ai-transport-mono.js.map +1 -0
  113. package/core/Icon/components/icon-product-ai-transport.js +2 -0
  114. package/core/Icon/components/icon-product-ai-transport.js.map +1 -0
  115. package/core/Icon/components/icon-product-chat-mono.js +1 -1
  116. package/core/Icon/components/icon-product-chat-mono.js.map +1 -1
  117. package/core/Icon/components/icon-product-liveobjects-mono.js +1 -1
  118. package/core/Icon/components/icon-product-liveobjects-mono.js.map +1 -1
  119. package/core/Icon/components/icon-product-livesync-mono.js +1 -1
  120. package/core/Icon/components/icon-product-livesync-mono.js.map +1 -1
  121. package/core/Icon/components/icon-product-pubsub-mono.js +1 -1
  122. package/core/Icon/components/icon-product-pubsub-mono.js.map +1 -1
  123. package/core/Icon/components/icon-product-spaces-mono.js +1 -1
  124. package/core/Icon/components/icon-product-spaces-mono.js.map +1 -1
  125. package/core/Icon/components/icon-tech-claude-mono.js +2 -0
  126. package/core/Icon/components/icon-tech-claude-mono.js.map +1 -0
  127. package/core/Icon/components/icon-tech-claude.js +2 -0
  128. package/core/Icon/components/icon-tech-claude.js.map +1 -0
  129. package/core/Icon/components/icon-tech-jetpack.js +2 -0
  130. package/core/Icon/components/icon-tech-jetpack.js.map +1 -0
  131. package/core/Icon/components/icon-tech-terraform-outline.js +2 -0
  132. package/core/Icon/components/icon-tech-terraform-outline.js.map +1 -0
  133. package/core/Icon/components/index.js +1 -1
  134. package/core/Icon/components/index.js.map +1 -1
  135. package/core/Icon/computed-icons/display-icons.js +1 -1
  136. package/core/Icon/computed-icons/display-icons.js.map +1 -1
  137. package/core/Icon/computed-icons/gui-icons.js +1 -1
  138. package/core/Icon/computed-icons/gui-icons.js.map +1 -1
  139. package/core/Icon/computed-icons/product-icons.js +1 -1
  140. package/core/Icon/computed-icons/product-icons.js.map +1 -1
  141. package/core/Icon/computed-icons/tech-icons.js +1 -1
  142. package/core/Icon/computed-icons/tech-icons.js.map +1 -1
  143. package/core/Icon.js +1 -1
  144. package/core/Icon.js.map +1 -1
  145. package/core/LinkButton.js +1 -1
  146. package/core/LinkButton.js.map +1 -1
  147. package/core/Logo.js +1 -1
  148. package/core/Logo.js.map +1 -1
  149. package/core/Meganav/MeganavBlog.js +2 -0
  150. package/core/Meganav/MeganavBlog.js.map +1 -0
  151. package/core/Meganav/MeganavCustomerStories.js +2 -0
  152. package/core/Meganav/MeganavCustomerStories.js.map +1 -0
  153. package/core/Meganav/MeganavMobile.js +1 -1
  154. package/core/Meganav/MeganavMobile.js.map +1 -1
  155. package/core/Meganav/MeganavPanel.js +1 -1
  156. package/core/Meganav/MeganavPanel.js.map +1 -1
  157. package/core/Meganav/MeganavPanelItemLinks.js +2 -0
  158. package/core/Meganav/MeganavPanelItemLinks.js.map +1 -0
  159. package/core/Meganav/MeganavTile.js +2 -0
  160. package/core/Meganav/MeganavTile.js.map +1 -0
  161. package/core/Meganav/PanelTitle.js +2 -0
  162. package/core/Meganav/PanelTitle.js.map +1 -0
  163. package/core/Meganav/data.js +1 -1
  164. package/core/Meganav/data.js.map +1 -1
  165. package/core/Meganav/images/cust-logo-doxy-dark.png +0 -0
  166. package/core/Meganav/images/cust-logo-doxy-light.png +0 -0
  167. package/core/Meganav/utils/getMenuItemsForHeader.js +2 -0
  168. package/core/Meganav/utils/getMenuItemsForHeader.js.map +1 -0
  169. package/core/Meganav.js +1 -1
  170. package/core/Meganav.js.map +1 -1
  171. package/core/Notice/component.css +9 -3
  172. package/core/Notice/component.js +1 -1
  173. package/core/Notice/component.js.map +1 -1
  174. package/core/Notice.js +1 -1
  175. package/core/Notice.js.map +1 -1
  176. package/core/Pricing/PricingCards.js +1 -1
  177. package/core/Pricing/PricingCards.js.map +1 -1
  178. package/core/Pricing/data.js +1 -1
  179. package/core/Pricing/data.js.map +1 -1
  180. package/core/Pricing/types.js.map +1 -1
  181. package/core/ProductTile/ProductDescription.js +1 -1
  182. package/core/ProductTile/ProductDescription.js.map +1 -1
  183. package/core/ProductTile/ProductIcon.js +1 -1
  184. package/core/ProductTile/ProductIcon.js.map +1 -1
  185. package/core/ProductTile/ProductLabel.js +1 -1
  186. package/core/ProductTile/ProductLabel.js.map +1 -1
  187. package/core/ProductTile/data.js +1 -1
  188. package/core/ProductTile/data.js.map +1 -1
  189. package/core/ProductTile.js +1 -1
  190. package/core/ProductTile.js.map +1 -1
  191. package/core/SegmentedControl.js +1 -1
  192. package/core/SegmentedControl.js.map +1 -1
  193. package/core/Slider/component.js +1 -1
  194. package/core/Slider/component.js.map +1 -1
  195. package/core/Slider.js +1 -1
  196. package/core/Slider.js.map +1 -1
  197. package/core/TabMenu.js +1 -1
  198. package/core/TabMenu.js.map +1 -1
  199. package/core/Table/data.js +1 -1
  200. package/core/Table/data.js.map +1 -1
  201. package/core/Toggle.js +1 -1
  202. package/core/Toggle.js.map +1 -1
  203. package/core/Tooltip.js +1 -1
  204. package/core/Tooltip.js.map +1 -1
  205. package/core/fonts/NEXT-Book-Light-Italic.eot +0 -0
  206. package/core/fonts/NEXT-Book-Light-Italic.otf +0 -0
  207. package/core/fonts/NEXT-Book-Light-Italic.woff +0 -0
  208. package/core/fonts/NEXT-Book-Light-Italic.woff2 +0 -0
  209. package/core/fonts/NEXT-Book-Light.eot +0 -0
  210. package/core/fonts/NEXT-Book-Light.otf +0 -0
  211. package/core/fonts/NEXT-Book-Light.woff +0 -0
  212. package/core/fonts/NEXT-Book-Light.woff2 +0 -0
  213. package/core/fonts/NEXT-Book-Medium-Italic.eot +0 -0
  214. package/core/fonts/NEXT-Book-Medium-Italic.otf +0 -0
  215. package/core/fonts/NEXT-Book-Medium-Italic.woff +0 -0
  216. package/core/fonts/NEXT-Book-Medium-Italic.woff2 +0 -0
  217. package/core/fonts/NEXT-Book-Medium.eot +0 -0
  218. package/core/fonts/NEXT-Book-Medium.otf +0 -0
  219. package/core/fonts/NEXT-Book-Medium.woff +0 -0
  220. package/core/fonts/NEXT-Book-Medium.woff2 +0 -0
  221. package/core/hooks/use-content-height.js +2 -0
  222. package/core/hooks/use-content-height.js.map +1 -0
  223. package/core/hooks/use-themed-scrollpoints.js +2 -0
  224. package/core/hooks/use-themed-scrollpoints.js.map +1 -0
  225. package/core/hooks/use-themed-scrollpoints.test.js +2 -0
  226. package/core/hooks/use-themed-scrollpoints.test.js.map +1 -0
  227. package/core/icons/display/icon-display-cloud-servers-mono.svg +3 -0
  228. package/core/icons/display/icon-display-data-integrity.svg +9 -0
  229. package/core/icons/display/icon-display-database-connector.svg +13 -0
  230. package/core/icons/display/icon-display-ephemeral-messages-dark-col.svg +6 -0
  231. package/core/icons/display/icon-display-ephemeral-messages.svg +6 -0
  232. package/core/icons/display/icon-display-live-updates.svg +8 -0
  233. package/core/icons/display/icon-display-message-annotations-dark-col.svg +11 -0
  234. package/core/icons/display/icon-display-message-annotations.svg +11 -0
  235. package/core/icons/display/icon-display-multi-user-spaces.svg +13 -0
  236. package/core/icons/display/icon-display-sdks.svg +11 -0
  237. package/core/icons/display/icon-display-something-else-mono.svg +4 -0
  238. package/core/icons/display/icon-display-something-else.svg +4 -0
  239. package/core/icons/display/icon-display-ui-mono.svg +22 -0
  240. package/core/icons/display/icon-display-ui.svg +22 -0
  241. package/core/icons/gui/icon-gui-checklist-checked.svg +1 -1
  242. package/core/icons/gui/icon-gui-code-doc.svg +1 -1
  243. package/core/icons/gui/icon-gui-cursor.svg +1 -1
  244. package/core/icons/gui/icon-gui-expand.svg +1 -1
  245. package/core/icons/gui/icon-gui-filter-flow-step-0.svg +3 -3
  246. package/core/icons/gui/icon-gui-flower-growth.svg +1 -1
  247. package/core/icons/gui/icon-gui-glasses.svg +1 -1
  248. package/core/icons/gui/icon-gui-heartbeat-outline.svg +4 -0
  249. package/core/icons/gui/icon-gui-heartbeat-solid.svg +4 -0
  250. package/core/icons/gui/icon-gui-mouse.svg +1 -1
  251. package/core/icons/gui/icon-gui-pitfall.svg +1 -1
  252. package/core/icons/gui/icon-gui-prod-ai-transport-outline.svg +5 -0
  253. package/core/icons/gui/icon-gui-prod-ai-transport-solid.svg +5 -0
  254. package/core/icons/gui/icon-gui-quote-marks-fill.svg +2 -2
  255. package/core/icons/product/icon-product-ai-transport-mono.svg +5 -0
  256. package/core/icons/product/icon-product-ai-transport.svg +12 -0
  257. package/core/icons/product/icon-product-chat-mono.svg +1 -1
  258. package/core/icons/product/icon-product-liveobjects-mono.svg +1 -4
  259. package/core/icons/product/icon-product-livesync-mono.svg +4 -4
  260. package/core/icons/product/icon-product-pubsub-mono.svg +1 -1
  261. package/core/icons/product/icon-product-spaces-mono.svg +1 -1
  262. package/core/icons/tech/icon-tech-claude-mono.svg +5 -0
  263. package/core/icons/tech/icon-tech-claude.svg +3 -0
  264. package/core/icons/tech/icon-tech-jetpack.svg +1 -0
  265. package/core/icons/tech/icon-tech-terraform-outline.svg +5 -0
  266. package/core/images/badges/g2-best-meets-requirements-spring-2025.svg +26 -0
  267. package/core/images/badges/g2-best-results-spring-2025.svg +26 -0
  268. package/core/images/badges/g2-best-support-spring-2025.svg +26 -0
  269. package/core/images/badges/g2-easiest-to-use-spring-2025.svg +26 -0
  270. package/core/images/badges/g2-users-most-likely-to-recommend-spring-2025.svg +26 -0
  271. package/core/images/cust-logo-mentimeter-mono-pos.svg +0 -0
  272. package/core/insights/command-queue.js +1 -1
  273. package/core/insights/command-queue.js.map +1 -1
  274. package/core/insights/datalayer.js +1 -1
  275. package/core/insights/datalayer.js.map +1 -1
  276. package/core/insights/index.js +1 -1
  277. package/core/insights/index.js.map +1 -1
  278. package/core/insights/index.test.js +1 -1
  279. package/core/insights/index.test.js.map +1 -1
  280. package/core/insights/mixpanel.js +1 -1
  281. package/core/insights/mixpanel.js.map +1 -1
  282. package/core/insights/mixpanel.test.js +2 -0
  283. package/core/insights/mixpanel.test.js.map +1 -0
  284. package/core/insights/posthog.js +1 -1
  285. package/core/insights/posthog.js.map +1 -1
  286. package/core/insights/posthog.test.js +2 -0
  287. package/core/insights/posthog.test.js.map +1 -0
  288. package/core/insights/service.js +1 -1
  289. package/core/insights/service.js.map +1 -1
  290. package/core/insights/types.js.map +1 -1
  291. package/core/react-renderer.js.map +1 -1
  292. package/core/sprites-display.svg +1 -1
  293. package/core/sprites-gui.svg +1 -1
  294. package/core/sprites-product.svg +1 -1
  295. package/core/sprites-tech.svg +1 -1
  296. package/core/styles/buttons.css +6 -6
  297. package/core/styles/colors/types.js +1 -1
  298. package/core/styles/colors/types.js.map +1 -1
  299. package/core/styles/forms.css +5 -5
  300. package/core/styles/legacy-buttons.css +8 -8
  301. package/core/styles/properties.css +4 -4
  302. package/core/styles/text.css +2 -2
  303. package/core/styles.components.css +4 -4
  304. package/core/utils/syntax-highlighter.css +31 -0
  305. package/core/utils/syntax-highlighter.js +1 -1
  306. package/core/utils/syntax-highlighter.js.map +1 -1
  307. package/core/utils/syntax-highlighter.test.js +2 -0
  308. package/core/utils/syntax-highlighter.test.js.map +1 -0
  309. package/index.d.ts +1201 -118
  310. package/package.json +66 -59
  311. package/tailwind.config.js +2 -2
  312. package/core/CookieMessage/component.css +0 -15
  313. package/core/CookieMessage.js +0 -2
  314. package/core/CookieMessage.js.map +0 -1
  315. package/core/Icon/components/icon-display-asset-tracking-col.js +0 -2
  316. package/core/Icon/components/icon-display-asset-tracking-col.js.map +0 -1
  317. package/core/Icon/components/icon-gui-prod-asset-tracking-outline.js +0 -2
  318. package/core/Icon/components/icon-gui-prod-asset-tracking-outline.js.map +0 -1
  319. package/core/Icon/components/icon-gui-prod-asset-tracking-solid.js +0 -2
  320. package/core/Icon/components/icon-gui-prod-asset-tracking-solid.js.map +0 -1
  321. package/core/Icon/components/icon-product-asset-tracking-mono.js +0 -2
  322. package/core/Icon/components/icon-product-asset-tracking-mono.js.map +0 -1
  323. package/core/Icon/components/icon-product-asset-tracking.js +0 -2
  324. package/core/Icon/components/icon-product-asset-tracking.js.map +0 -1
  325. package/core/Meganav/MeganavProductTile.js +0 -2
  326. package/core/Meganav/MeganavProductTile.js.map +0 -1
  327. package/core/Meganav/images/fan-engagement-nav-image.png +0 -0
  328. package/core/Meganav/images/founders-nav-image.png +0 -0
  329. package/core/icons/display/icon-display-asset-tracking-col.svg +0 -18
  330. package/core/icons/gui/icon-gui-prod-asset-tracking-outline.svg +0 -3
  331. package/core/icons/gui/icon-gui-prod-asset-tracking-solid.svg +0 -3
  332. package/core/icons/product/icon-product-asset-tracking-mono.svg +0 -3
  333. package/core/icons/product/icon-product-asset-tracking.svg +0 -12
  334. package/core/images/g2-best-meets-requirements-2025.svg +0 -10
  335. package/core/images/g2-best-support-2025.svg +0 -10
  336. package/core/images/g2-high-performer-2025.svg +0 -9
  337. package/core/images/g2-users-most-likely-to-recommend-2025.svg +0 -10
  338. package/core/utils/useCopyToClipboard.js +0 -2
  339. package/core/utils/useCopyToClipboard.js.map +0 -1
@@ -1,2 +1,2 @@
1
- import{describe,expect,beforeEach,afterEach,it,vi}from"vitest";import*as datalayer from"./datalayer";import*as mixpanel from"./mixpanel";import*as posthog from"./posthog";import*as logger from"./logger";import*as insights from"./index";vi.mock("./datalayer",()=>({track:vi.fn()}));vi.mock("./mixpanel",()=>({initMixpanel:vi.fn(),enableDebugMode:vi.fn(),disableDebugMode:vi.fn(),identify:vi.fn(),trackPageView:vi.fn(),track:vi.fn(),startSessionRecording:vi.fn(),stopSessionRecording:vi.fn()}));vi.mock("./posthog",()=>({initPosthog:vi.fn(),enableDebugMode:vi.fn(),disableDebugMode:vi.fn(),identify:vi.fn(),trackPageView:vi.fn(),track:vi.fn(),startSessionRecording:vi.fn(),stopSessionRecording:vi.fn()}));vi.mock("./logger",()=>({debug:vi.fn(),info:vi.fn(),warn:vi.fn(),error:vi.fn()}));describe("Insights Command Queue",()=>{const testConfig={debug:true,mixpanelToken:"test-token",mixpanelAutoCapture:false,mixpanelRecordSessionsPercent:10,posthogApiKey:"test-key",posthogApiHost:"test-host"};const testIdentity={userId:"user-123",accountId:"account-456",organisationId:"org-789",email:"test@example.com",name:"Test User"};beforeEach(()=>{vi.clearAllMocks();vi.resetModules()});afterEach(()=>{document.body.replaceWith(document.body.cloneNode(true))});describe("Pre-initialization Queueing",()=>{it("should queue methods called before initialization",async()=>{insights.track("early_event",{early:true});insights.identify(testIdentity);insights.trackPageView();expect(mixpanel.track).not.toHaveBeenCalled();expect(posthog.track).not.toHaveBeenCalled();expect(datalayer.track).not.toHaveBeenCalled();expect(mixpanel.identify).not.toHaveBeenCalled();expect(posthog.identify).not.toHaveBeenCalled();expect(mixpanel.trackPageView).not.toHaveBeenCalled();expect(posthog.trackPageView).not.toHaveBeenCalled();insights.initInsights(testConfig);expect(mixpanel.initMixpanel).toHaveBeenCalledWith(testConfig.mixpanelToken,testConfig.mixpanelAutoCapture,testConfig.debug,testConfig.mixpanelRecordSessionsPercent);expect(posthog.initPosthog).toHaveBeenCalledWith(testConfig.posthogApiKey,testConfig.posthogApiHost);expect(mixpanel.track).toHaveBeenCalledWith("early_event",{early:true});expect(posthog.track).toHaveBeenCalledWith("early_event",{early:true});expect(datalayer.track).toHaveBeenCalledWith("early_event",{early:true});expect(mixpanel.identify).toHaveBeenCalledWith(testIdentity);expect(posthog.identify).toHaveBeenCalledWith(testIdentity);expect(mixpanel.trackPageView).toHaveBeenCalled();expect(posthog.trackPageView).toHaveBeenCalled()});it("should handle errors in queued methods gracefully",async()=>{mixpanel.track.mockImplementationOnce(()=>{throw new Error("Mixpanel error")});insights.track("error_event",{error:true});insights.trackPageView();insights.initInsights(testConfig);expect(logger.error).toHaveBeenCalledWith(expect.stringContaining("Failed to track event in Mixpanel"),expect.any(Error));expect(posthog.track).toHaveBeenCalledWith("error_event",{error:true});expect(datalayer.track).toHaveBeenCalledWith("error_event",{error:true});expect(mixpanel.trackPageView).toHaveBeenCalled();expect(posthog.trackPageView).toHaveBeenCalled()})});describe("Post-initialization Direct Execution",()=>{beforeEach(()=>{insights.initInsights(testConfig);vi.clearAllMocks()});it("should directly call methods after initialization",()=>{insights.track("post_init_event",{post:true});expect(mixpanel.track).toHaveBeenCalledWith("post_init_event",{post:true});expect(posthog.track).toHaveBeenCalledWith("post_init_event",{post:true});expect(datalayer.track).toHaveBeenCalledWith("post_init_event",{post:true})});it("should handle all exported methods correctly",()=>{insights.identify(testIdentity);expect(mixpanel.identify).toHaveBeenCalledWith(testIdentity);expect(posthog.identify).toHaveBeenCalledWith(testIdentity);insights.trackPageView();expect(mixpanel.trackPageView).toHaveBeenCalled();expect(posthog.trackPageView).toHaveBeenCalled();insights.startSessionRecording();expect(mixpanel.startSessionRecording).toHaveBeenCalled();expect(posthog.startSessionRecording).toHaveBeenCalled();insights.stopSessionRecording();expect(mixpanel.stopSessionRecording).toHaveBeenCalled();expect(posthog.stopSessionRecording).toHaveBeenCalled();insights.enableDebugMode();expect(mixpanel.enableDebugMode).toHaveBeenCalled();expect(posthog.enableDebugMode).toHaveBeenCalled();insights.disableDebugMode();expect(mixpanel.disableDebugMode).toHaveBeenCalled();expect(posthog.disableDebugMode).toHaveBeenCalled()})});describe("Observer Setup",()=>{beforeEach(()=>{insights.initInsights(testConfig);vi.clearAllMocks()});it("should set up click event observer and track clicks",()=>{const cleanup=insights.setupObserver();const testElement=document.createElement("button");testElement.setAttribute("data-insight-event","button_clicked");testElement.setAttribute("data-insight-button-id","test-123");document.body.appendChild(testElement);testElement.click();expect(mixpanel.track).toHaveBeenCalledWith("button_clicked",{buttonId:"test-123"});expect(posthog.track).toHaveBeenCalledWith("button_clicked",{buttonId:"test-123"});expect(datalayer.track).toHaveBeenCalledWith("button_clicked",{buttonId:"test-123"});cleanup();vi.clearAllMocks();testElement.click();expect(mixpanel.track).not.toHaveBeenCalled()});it("should handle nested elements correctly",()=>{insights.setupObserver();const parentElement=document.createElement("div");parentElement.setAttribute("data-insight-event","container_clicked");parentElement.setAttribute("data-insight-container-id","parent-container");const childElement=document.createElement("span");childElement.textContent="Click me";parentElement.appendChild(childElement);document.body.appendChild(parentElement);childElement.click();expect(mixpanel.track).toHaveBeenCalledWith("container_clicked",{containerId:"parent-container"})})});describe("Error Handling",()=>{it("should handle initialization errors gracefully",()=>{mixpanel.initMixpanel.mockImplementationOnce(()=>{throw new Error("Mixpanel init error")});expect(()=>{insights.initInsights(testConfig)}).not.toThrow();expect(logger.error).toHaveBeenCalledWith(expect.stringContaining("Failed to initialize Mixpanel"),expect.any(Error))});it("should handle runtime errors in methods",()=>{insights.initInsights(testConfig);vi.clearAllMocks();mixpanel.track.mockImplementationOnce(()=>{throw new Error("Mixpanel track error")});posthog.track.mockImplementationOnce(()=>{throw new Error("Posthog track error")});expect(()=>{insights.track("error_test",{test:true})}).not.toThrow();expect(logger.error).toHaveBeenCalledWith(expect.stringContaining("Failed to track event in Mixpanel"),expect.any(Error));expect(logger.error).toHaveBeenCalledWith(expect.stringContaining("Failed to track event in Posthog"),expect.any(Error));expect(datalayer.track).toHaveBeenCalledWith("error_test",{test:true})})});describe("Debug Mode",()=>{it("should respect debug flag in config",()=>{insights.initInsights(testConfig);expect(logger.debug).toHaveBeenCalledWith(expect.stringContaining("Initializing insights"));vi.clearAllMocks();insights.track("debug_test",{debug:true});expect(logger.info).toHaveBeenCalledWith(expect.stringContaining("Tracking event"),expect.objectContaining({event:"debug_test",properties:{debug:true}}))});it("should not log debug info when debug is false",()=>{insights.initInsights({...testConfig,debug:false});vi.clearAllMocks();insights.track("no_debug_test",{debug:false});expect(logger.info).not.toHaveBeenCalled()})})});
1
+ import{describe,expect,beforeEach,afterEach,it,vi}from"vitest";import*as datalayer from"./datalayer";import*as mixpanel from"./mixpanel";import*as posthog from"./posthog";import*as logger from"./logger";import*as insights from"./index";vi.mock("./datalayer",()=>({track:vi.fn(),trackPageView:vi.fn()}));vi.mock("./mixpanel",()=>({initMixpanel:vi.fn(),enableDebugMode:vi.fn(),disableDebugMode:vi.fn(),identify:vi.fn(),trackPageView:vi.fn(),track:vi.fn(),startSessionRecording:vi.fn(),stopSessionRecording:vi.fn()}));vi.mock("./posthog",()=>({initPosthog:vi.fn(),enableDebugMode:vi.fn(),disableDebugMode:vi.fn(),identify:vi.fn(),trackPageView:vi.fn(),track:vi.fn(),startSessionRecording:vi.fn(),stopSessionRecording:vi.fn()}));vi.mock("./logger",()=>({debug:vi.fn(),info:vi.fn(),warn:vi.fn(),error:vi.fn()}));describe("Insights Command Queue",()=>{const testConfig={debug:true,mixpanelToken:"test-token",mixpanelAutoCapture:false,mixpanelRecordSessionsPercent:10,posthogApiKey:"test-key",posthogApiHost:"test-host"};const testIdentity={userId:"user-123",accountId:"account-456",organisationId:"org-789",email:"test@example.com",name:"Test User"};beforeEach(()=>{vi.clearAllMocks();vi.resetModules()});afterEach(()=>{document.body.replaceWith(document.body.cloneNode(true))});describe("Pre-initialization Queueing",()=>{it("should queue methods called before initialization",async()=>{insights.track("early_event",{early:true});insights.identify(testIdentity);insights.trackPageView();expect(mixpanel.track).not.toHaveBeenCalled();expect(posthog.track).not.toHaveBeenCalled();expect(datalayer.track).not.toHaveBeenCalled();expect(mixpanel.identify).not.toHaveBeenCalled();expect(posthog.identify).not.toHaveBeenCalled();expect(mixpanel.trackPageView).not.toHaveBeenCalled();expect(posthog.trackPageView).not.toHaveBeenCalled();expect(datalayer.trackPageView).not.toHaveBeenCalled();insights.initInsights(testConfig);expect(mixpanel.initMixpanel).toHaveBeenCalledWith(testConfig.mixpanelToken,testConfig.mixpanelAutoCapture,testConfig.debug,testConfig.mixpanelRecordSessionsPercent);expect(posthog.initPosthog).toHaveBeenCalledWith(testConfig.posthogApiKey,testConfig.posthogApiHost);expect(mixpanel.track).toHaveBeenCalledWith("early_event",{early:true});expect(posthog.track).toHaveBeenCalledWith("early_event",{early:true});expect(datalayer.track).toHaveBeenCalledWith("early_event",{early:true});expect(mixpanel.identify).toHaveBeenCalledWith(testIdentity);expect(posthog.identify).toHaveBeenCalledWith(testIdentity);expect(mixpanel.trackPageView).toHaveBeenCalled();expect(posthog.trackPageView).toHaveBeenCalled();expect(datalayer.trackPageView).not.toHaveBeenCalled()});it("should handle errors in queued methods gracefully",async()=>{mixpanel.track.mockImplementationOnce(()=>{throw new Error("Mixpanel error")});insights.track("error_event",{error:true});insights.trackPageView();insights.initInsights(testConfig);expect(logger.error).toHaveBeenCalledWith(expect.stringContaining("Failed to track event in Mixpanel"),expect.any(Error));expect(posthog.track).toHaveBeenCalledWith("error_event",{error:true});expect(datalayer.track).toHaveBeenCalledWith("error_event",{error:true});expect(mixpanel.trackPageView).toHaveBeenCalled();expect(posthog.trackPageView).toHaveBeenCalled();expect(datalayer.trackPageView).not.toHaveBeenCalled()});it("should report page view to GTM as well when includeDataLayer is true",()=>{insights.trackPageView({includeDataLayer:true});expect(mixpanel.trackPageView).toHaveBeenCalled();expect(posthog.trackPageView).toHaveBeenCalled();expect(datalayer.trackPageView).toHaveBeenCalled()})});describe("Post-initialization Direct Execution",()=>{beforeEach(()=>{insights.initInsights(testConfig);vi.clearAllMocks()});it("should directly call methods after initialization",()=>{insights.track("post_init_event",{post:true});expect(mixpanel.track).toHaveBeenCalledWith("post_init_event",{post:true});expect(posthog.track).toHaveBeenCalledWith("post_init_event",{post:true});expect(datalayer.track).toHaveBeenCalledWith("post_init_event",{post:true})});it("should handle all exported methods correctly",()=>{insights.identify(testIdentity);expect(mixpanel.identify).toHaveBeenCalledWith(testIdentity);expect(posthog.identify).toHaveBeenCalledWith(testIdentity);insights.trackPageView();expect(mixpanel.trackPageView).toHaveBeenCalled();expect(posthog.trackPageView).toHaveBeenCalled();expect(datalayer.trackPageView).not.toHaveBeenCalled();insights.startSessionRecording();expect(mixpanel.startSessionRecording).toHaveBeenCalled();expect(posthog.startSessionRecording).toHaveBeenCalled();insights.stopSessionRecording();expect(mixpanel.stopSessionRecording).toHaveBeenCalled();expect(posthog.stopSessionRecording).toHaveBeenCalled();insights.enableDebugMode();expect(mixpanel.enableDebugMode).toHaveBeenCalled();expect(posthog.enableDebugMode).toHaveBeenCalled();insights.disableDebugMode();expect(mixpanel.disableDebugMode).toHaveBeenCalled();expect(posthog.disableDebugMode).toHaveBeenCalled()});it("should report page view to GTM as well when includeDataLayer is true",()=>{insights.trackPageView({includeDataLayer:true});expect(mixpanel.trackPageView).toHaveBeenCalled();expect(posthog.trackPageView).toHaveBeenCalled();expect(datalayer.trackPageView).toHaveBeenCalled()})});describe("Observer Setup",()=>{beforeEach(()=>{insights.initInsights(testConfig);vi.clearAllMocks()});it("should set up click event observer and track clicks",()=>{const cleanup=insights.setupObserver();const testElement=document.createElement("button");testElement.setAttribute("data-insight-event","button_clicked");testElement.setAttribute("data-insight-button-id","test-123");document.body.appendChild(testElement);testElement.click();expect(mixpanel.track).toHaveBeenCalledWith("button_clicked",{buttonId:"test-123"});expect(posthog.track).toHaveBeenCalledWith("button_clicked",{buttonId:"test-123"});expect(datalayer.track).toHaveBeenCalledWith("button_clicked",{buttonId:"test-123"});cleanup();vi.clearAllMocks();testElement.click();expect(mixpanel.track).not.toHaveBeenCalled()});it("should handle nested elements correctly",()=>{insights.setupObserver();const parentElement=document.createElement("div");parentElement.setAttribute("data-insight-event","container_clicked");parentElement.setAttribute("data-insight-container-id","parent-container");const childElement=document.createElement("span");childElement.textContent="Click me";parentElement.appendChild(childElement);document.body.appendChild(parentElement);childElement.click();expect(mixpanel.track).toHaveBeenCalledWith("container_clicked",{containerId:"parent-container"})})});describe("Error Handling",()=>{it("should handle initialization errors gracefully",()=>{mixpanel.initMixpanel.mockImplementationOnce(()=>{throw new Error("Mixpanel init error")});expect(()=>{insights.initInsights(testConfig)}).not.toThrow();expect(logger.error).toHaveBeenCalledWith(expect.stringContaining("Failed to initialize Mixpanel"),expect.any(Error))});it("should handle runtime errors in methods",()=>{insights.initInsights(testConfig);vi.clearAllMocks();mixpanel.track.mockImplementationOnce(()=>{throw new Error("Mixpanel track error")});posthog.track.mockImplementationOnce(()=>{throw new Error("Posthog track error")});expect(()=>{insights.track("error_test",{test:true})}).not.toThrow();expect(logger.error).toHaveBeenCalledWith(expect.stringContaining("Failed to track event in Mixpanel"),expect.any(Error));expect(logger.error).toHaveBeenCalledWith(expect.stringContaining("Failed to track event in Posthog"),expect.any(Error));expect(datalayer.track).toHaveBeenCalledWith("error_test",{test:true})})});describe("Debug Mode",()=>{it("should respect debug flag in config",()=>{insights.initInsights(testConfig);expect(logger.debug).toHaveBeenCalledWith(expect.stringContaining("Initializing insights"));vi.clearAllMocks();insights.track("debug_test",{debug:true});expect(logger.info).toHaveBeenCalledWith(expect.stringContaining("Tracking event"),expect.objectContaining({event:"debug_test",properties:{debug:true}}))});it("should not log debug info when debug is false",()=>{insights.initInsights({...testConfig,debug:false});vi.clearAllMocks();insights.track("no_debug_test",{debug:false});expect(logger.info).not.toHaveBeenCalled()})});describe("Arbitrary Properties",()=>{const customPageViewProperties={customProperty:"custom-value",anotherProperty:123,nestedObject:{foo:"bar"}};const customPageViewPropertiesWithDataLayer={customProperty:"custom-value",anotherProperty:456};const customPageViewPropertiesWithExcludeIds={customProperty:"test",count:789};const customIdentityProperties={customProperty:"user-custom-value",userSegment:"premium",signupDate:"2024-01-01"};const customMinimalIdentityProperties={customField1:"value1",customField2:999,customField3:{nested:true}};beforeEach(()=>{insights.initInsights(testConfig);vi.clearAllMocks()});it("should pass arbitrary properties through trackPageView",()=>{insights.trackPageView(customPageViewProperties);expect(mixpanel.trackPageView).toHaveBeenCalledWith(customPageViewProperties);expect(posthog.trackPageView).toHaveBeenCalledWith(customPageViewProperties);expect(datalayer.trackPageView).not.toHaveBeenCalled()});it("should pass arbitrary properties through trackPageView with includeDataLayer",()=>{insights.trackPageView({includeDataLayer:true,...customPageViewPropertiesWithDataLayer});expect(mixpanel.trackPageView).toHaveBeenCalledWith(customPageViewPropertiesWithDataLayer);expect(posthog.trackPageView).toHaveBeenCalledWith(customPageViewPropertiesWithDataLayer);expect(datalayer.trackPageView).toHaveBeenCalledWith(customPageViewPropertiesWithDataLayer)});it("should pass arbitrary properties through trackPageView with excludeIds",()=>{const excludeIds=["id1","id2"];insights.trackPageView({excludeIds,...customPageViewPropertiesWithExcludeIds});expect(mixpanel.trackPageView).toHaveBeenCalledWith({excludeIds,...customPageViewPropertiesWithExcludeIds});expect(posthog.trackPageView).toHaveBeenCalledWith(customPageViewPropertiesWithExcludeIds)});it("should pass arbitrary properties through identify",()=>{const identityWithCustomProps={...testIdentity,...customIdentityProperties};insights.identify(identityWithCustomProps);expect(mixpanel.identify).toHaveBeenCalledWith(identityWithCustomProps);expect(posthog.identify).toHaveBeenCalledWith(identityWithCustomProps)});it("should pass arbitrary properties through identify with minimal identity",()=>{const minimalIdentity={userId:"minimal-user",accountId:"minimal-account",...customMinimalIdentityProperties};insights.identify(minimalIdentity);expect(mixpanel.identify).toHaveBeenCalledWith(minimalIdentity);expect(posthog.identify).toHaveBeenCalledWith(minimalIdentity)})})});
2
2
  //# sourceMappingURL=index.test.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/core/insights/index.test.ts"],"sourcesContent":["/**\n * @vitest-environment jsdom\n */\n\nimport { describe, expect, beforeEach, afterEach, it, vi } from \"vitest\";\n\nimport * as datalayer from \"./datalayer\";\nimport * as mixpanel from \"./mixpanel\";\nimport * as posthog from \"./posthog\";\nimport * as logger from \"./logger\";\nimport * as insights from \"./index\";\n\n// Mock the dependencies\nvi.mock(\"./datalayer\", () => ({\n track: vi.fn(),\n}));\n\nvi.mock(\"./mixpanel\", () => ({\n initMixpanel: vi.fn(),\n enableDebugMode: vi.fn(),\n disableDebugMode: vi.fn(),\n identify: vi.fn(),\n trackPageView: vi.fn(),\n track: vi.fn(),\n startSessionRecording: vi.fn(),\n stopSessionRecording: vi.fn(),\n}));\n\nvi.mock(\"./posthog\", () => ({\n initPosthog: vi.fn(),\n enableDebugMode: vi.fn(),\n disableDebugMode: vi.fn(),\n identify: vi.fn(),\n trackPageView: vi.fn(),\n track: vi.fn(),\n startSessionRecording: vi.fn(),\n stopSessionRecording: vi.fn(),\n}));\n\nvi.mock(\"./logger\", () => ({\n debug: vi.fn(),\n info: vi.fn(),\n warn: vi.fn(),\n error: vi.fn(),\n}));\n\ndescribe(\"Insights Command Queue\", () => {\n const testConfig = {\n debug: true,\n mixpanelToken: \"test-token\",\n mixpanelAutoCapture: false,\n mixpanelRecordSessionsPercent: 10,\n posthogApiKey: \"test-key\",\n posthogApiHost: \"test-host\",\n };\n\n const testIdentity = {\n userId: \"user-123\",\n accountId: \"account-456\",\n organisationId: \"org-789\",\n email: \"test@example.com\",\n name: \"Test User\",\n };\n\n beforeEach(() => {\n // Clear all mocks before each test\n vi.clearAllMocks();\n\n // Reset the module to clear any internal state\n vi.resetModules();\n });\n\n afterEach(() => {\n // Cleanup document event listeners\n document.body.replaceWith(document.body.cloneNode(true));\n });\n\n describe(\"Pre-initialization Queueing\", () => {\n it(\"should queue methods called before initialization\", async () => {\n // Call methods before initialization\n insights.track(\"early_event\", { early: true });\n insights.identify(testIdentity);\n insights.trackPageView();\n\n // Verify nothing has been called yet on the underlying services\n expect(mixpanel.track).not.toHaveBeenCalled();\n expect(posthog.track).not.toHaveBeenCalled();\n expect(datalayer.track).not.toHaveBeenCalled();\n expect(mixpanel.identify).not.toHaveBeenCalled();\n expect(posthog.identify).not.toHaveBeenCalled();\n expect(mixpanel.trackPageView).not.toHaveBeenCalled();\n expect(posthog.trackPageView).not.toHaveBeenCalled();\n\n // Now initialize\n insights.initInsights(testConfig);\n\n // Initialize should be called immediately\n expect(mixpanel.initMixpanel).toHaveBeenCalledWith(\n testConfig.mixpanelToken,\n testConfig.mixpanelAutoCapture,\n testConfig.debug,\n testConfig.mixpanelRecordSessionsPercent,\n );\n expect(posthog.initPosthog).toHaveBeenCalledWith(\n testConfig.posthogApiKey,\n testConfig.posthogApiHost,\n );\n\n // Queued methods should now be called in the correct order\n expect(mixpanel.track).toHaveBeenCalledWith(\"early_event\", {\n early: true,\n });\n expect(posthog.track).toHaveBeenCalledWith(\"early_event\", {\n early: true,\n });\n expect(datalayer.track).toHaveBeenCalledWith(\"early_event\", {\n early: true,\n });\n\n expect(mixpanel.identify).toHaveBeenCalledWith(testIdentity);\n expect(posthog.identify).toHaveBeenCalledWith(testIdentity);\n\n expect(mixpanel.trackPageView).toHaveBeenCalled();\n expect(posthog.trackPageView).toHaveBeenCalled();\n });\n\n it(\"should handle errors in queued methods gracefully\", async () => {\n // Setup an error for one of the methods\n mixpanel.track.mockImplementationOnce(() => {\n throw new Error(\"Mixpanel error\");\n });\n\n // Call methods before initialization\n insights.track(\"error_event\", { error: true });\n insights.trackPageView();\n\n // Now initialize\n insights.initInsights(testConfig);\n\n // Should have logged the error but continued processing the queue\n expect(logger.error).toHaveBeenCalledWith(\n expect.stringContaining(\"Failed to track event in Mixpanel\"),\n expect.any(Error),\n );\n\n // The other methods should still be called\n expect(posthog.track).toHaveBeenCalledWith(\"error_event\", {\n error: true,\n });\n expect(datalayer.track).toHaveBeenCalledWith(\"error_event\", {\n error: true,\n });\n expect(mixpanel.trackPageView).toHaveBeenCalled();\n expect(posthog.trackPageView).toHaveBeenCalled();\n });\n });\n\n describe(\"Post-initialization Direct Execution\", () => {\n beforeEach(() => {\n // Initialize first\n insights.initInsights(testConfig);\n // Clear the mocks to focus on post-init behavior\n vi.clearAllMocks();\n });\n\n it(\"should directly call methods after initialization\", () => {\n // Call methods after initialization\n insights.track(\"post_init_event\", { post: true });\n\n // Should be called immediately\n expect(mixpanel.track).toHaveBeenCalledWith(\"post_init_event\", {\n post: true,\n });\n expect(posthog.track).toHaveBeenCalledWith(\"post_init_event\", {\n post: true,\n });\n expect(datalayer.track).toHaveBeenCalledWith(\"post_init_event\", {\n post: true,\n });\n });\n\n it(\"should handle all exported methods correctly\", () => {\n // Test each exported method\n insights.identify(testIdentity);\n expect(mixpanel.identify).toHaveBeenCalledWith(testIdentity);\n expect(posthog.identify).toHaveBeenCalledWith(testIdentity);\n\n insights.trackPageView();\n expect(mixpanel.trackPageView).toHaveBeenCalled();\n expect(posthog.trackPageView).toHaveBeenCalled();\n\n insights.startSessionRecording();\n expect(mixpanel.startSessionRecording).toHaveBeenCalled();\n expect(posthog.startSessionRecording).toHaveBeenCalled();\n\n insights.stopSessionRecording();\n expect(mixpanel.stopSessionRecording).toHaveBeenCalled();\n expect(posthog.stopSessionRecording).toHaveBeenCalled();\n\n insights.enableDebugMode();\n expect(mixpanel.enableDebugMode).toHaveBeenCalled();\n expect(posthog.enableDebugMode).toHaveBeenCalled();\n\n insights.disableDebugMode();\n expect(mixpanel.disableDebugMode).toHaveBeenCalled();\n expect(posthog.disableDebugMode).toHaveBeenCalled();\n });\n });\n\n describe(\"Observer Setup\", () => {\n beforeEach(() => {\n insights.initInsights(testConfig);\n vi.clearAllMocks();\n });\n\n it(\"should set up click event observer and track clicks\", () => {\n // Setup observer\n const cleanup = insights.setupObserver();\n\n // Create a test element with insight attributes\n const testElement = document.createElement(\"button\");\n testElement.setAttribute(\"data-insight-event\", \"button_clicked\");\n testElement.setAttribute(\"data-insight-button-id\", \"test-123\");\n document.body.appendChild(testElement);\n\n // Simulate click\n testElement.click();\n\n // Should track the event\n expect(mixpanel.track).toHaveBeenCalledWith(\"button_clicked\", {\n buttonId: \"test-123\",\n });\n expect(posthog.track).toHaveBeenCalledWith(\"button_clicked\", {\n buttonId: \"test-123\",\n });\n expect(datalayer.track).toHaveBeenCalledWith(\"button_clicked\", {\n buttonId: \"test-123\",\n });\n\n // Test cleanup\n cleanup();\n\n // Reset tracking mocks\n vi.clearAllMocks();\n\n // Click again - should not track\n testElement.click();\n expect(mixpanel.track).not.toHaveBeenCalled();\n });\n\n it(\"should handle nested elements correctly\", () => {\n // Setup observer\n insights.setupObserver();\n\n // Create parent element with insight attributes\n const parentElement = document.createElement(\"div\");\n parentElement.setAttribute(\"data-insight-event\", \"container_clicked\");\n parentElement.setAttribute(\n \"data-insight-container-id\",\n \"parent-container\",\n );\n\n // Create child element without insights\n const childElement = document.createElement(\"span\");\n childElement.textContent = \"Click me\";\n\n // Nest elements\n parentElement.appendChild(childElement);\n document.body.appendChild(parentElement);\n\n // Click the child element\n childElement.click();\n\n // Should find and use the parent's insight attributes\n expect(mixpanel.track).toHaveBeenCalledWith(\"container_clicked\", {\n containerId: \"parent-container\",\n });\n });\n });\n\n describe(\"Error Handling\", () => {\n it(\"should handle initialization errors gracefully\", () => {\n // Setup an error in initialization\n mixpanel.initMixpanel.mockImplementationOnce(() => {\n throw new Error(\"Mixpanel init error\");\n });\n\n // Should not throw when initializing\n expect(() => {\n insights.initInsights(testConfig);\n }).not.toThrow();\n\n // Should log the error\n expect(logger.error).toHaveBeenCalledWith(\n expect.stringContaining(\"Failed to initialize Mixpanel\"),\n expect.any(Error),\n );\n });\n\n it(\"should handle runtime errors in methods\", () => {\n // Initialize first\n insights.initInsights(testConfig);\n vi.clearAllMocks();\n\n // Setup errors in tracking\n mixpanel.track.mockImplementationOnce(() => {\n throw new Error(\"Mixpanel track error\");\n });\n\n posthog.track.mockImplementationOnce(() => {\n throw new Error(\"Posthog track error\");\n });\n\n // Should not throw when tracking\n expect(() => {\n insights.track(\"error_test\", { test: true });\n }).not.toThrow();\n\n // Should log the errors\n expect(logger.error).toHaveBeenCalledWith(\n expect.stringContaining(\"Failed to track event in Mixpanel\"),\n expect.any(Error),\n );\n\n expect(logger.error).toHaveBeenCalledWith(\n expect.stringContaining(\"Failed to track event in Posthog\"),\n expect.any(Error),\n );\n\n // Should still try to track with datalayer\n expect(datalayer.track).toHaveBeenCalledWith(\"error_test\", {\n test: true,\n });\n });\n });\n\n describe(\"Debug Mode\", () => {\n it(\"should respect debug flag in config\", () => {\n // Initialize with debug: true\n insights.initInsights(testConfig);\n\n // Should log debug messages\n expect(logger.debug).toHaveBeenCalledWith(\n expect.stringContaining(\"Initializing insights\"),\n );\n\n // Clear mocks and test tracking\n vi.clearAllMocks();\n insights.track(\"debug_test\", { debug: true });\n\n // Should log info about tracking\n expect(logger.info).toHaveBeenCalledWith(\n expect.stringContaining(\"Tracking event\"),\n expect.objectContaining({\n event: \"debug_test\",\n properties: { debug: true },\n }),\n );\n });\n\n it(\"should not log debug info when debug is false\", () => {\n // Initialize with debug: false\n insights.initInsights({\n ...testConfig,\n debug: false,\n });\n\n // Clear mocks and test tracking\n vi.clearAllMocks();\n insights.track(\"no_debug_test\", { debug: false });\n\n // Should not log info about tracking\n expect(logger.info).not.toHaveBeenCalled();\n });\n });\n});\n"],"names":["describe","expect","beforeEach","afterEach","it","vi","datalayer","mixpanel","posthog","logger","insights","mock","track","fn","initMixpanel","enableDebugMode","disableDebugMode","identify","trackPageView","startSessionRecording","stopSessionRecording","initPosthog","debug","info","warn","error","testConfig","mixpanelToken","mixpanelAutoCapture","mixpanelRecordSessionsPercent","posthogApiKey","posthogApiHost","testIdentity","userId","accountId","organisationId","email","name","clearAllMocks","resetModules","document","body","replaceWith","cloneNode","early","not","toHaveBeenCalled","initInsights","toHaveBeenCalledWith","mockImplementationOnce","Error","stringContaining","any","post","cleanup","setupObserver","testElement","createElement","setAttribute","appendChild","click","buttonId","parentElement","childElement","textContent","containerId","toThrow","test","objectContaining","event","properties"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../src/core/insights/index.test.ts"],"sourcesContent":["/**\n * @vitest-environment jsdom\n */\n\nimport { describe, expect, beforeEach, afterEach, it, vi, Mock } from \"vitest\";\n\nimport * as datalayer from \"./datalayer\";\nimport * as mixpanel from \"./mixpanel\";\nimport * as posthog from \"./posthog\";\nimport * as logger from \"./logger\";\nimport * as insights from \"./index\";\n\n// Mock the dependencies\nvi.mock(\"./datalayer\", () => ({\n track: vi.fn(),\n trackPageView: vi.fn(),\n}));\n\nvi.mock(\"./mixpanel\", () => ({\n initMixpanel: vi.fn(),\n enableDebugMode: vi.fn(),\n disableDebugMode: vi.fn(),\n identify: vi.fn(),\n trackPageView: vi.fn(),\n track: vi.fn(),\n startSessionRecording: vi.fn(),\n stopSessionRecording: vi.fn(),\n}));\n\nvi.mock(\"./posthog\", () => ({\n initPosthog: vi.fn(),\n enableDebugMode: vi.fn(),\n disableDebugMode: vi.fn(),\n identify: vi.fn(),\n trackPageView: vi.fn(),\n track: vi.fn(),\n startSessionRecording: vi.fn(),\n stopSessionRecording: vi.fn(),\n}));\n\nvi.mock(\"./logger\", () => ({\n debug: vi.fn(),\n info: vi.fn(),\n warn: vi.fn(),\n error: vi.fn(),\n}));\n\ndescribe(\"Insights Command Queue\", () => {\n const testConfig = {\n debug: true,\n mixpanelToken: \"test-token\",\n mixpanelAutoCapture: false,\n mixpanelRecordSessionsPercent: 10,\n posthogApiKey: \"test-key\",\n posthogApiHost: \"test-host\",\n };\n\n const testIdentity = {\n userId: \"user-123\",\n accountId: \"account-456\",\n organisationId: \"org-789\",\n email: \"test@example.com\",\n name: \"Test User\",\n };\n\n beforeEach(() => {\n // Clear all mocks before each test\n vi.clearAllMocks();\n\n // Reset the module to clear any internal state\n vi.resetModules();\n });\n\n afterEach(() => {\n // Cleanup document event listeners\n document.body.replaceWith(document.body.cloneNode(true));\n });\n\n describe(\"Pre-initialization Queueing\", () => {\n it(\"should queue methods called before initialization\", async () => {\n // Call methods before initialization\n insights.track(\"early_event\", { early: true });\n insights.identify(testIdentity);\n insights.trackPageView();\n\n // Verify nothing has been called yet on the underlying services\n expect(mixpanel.track).not.toHaveBeenCalled();\n expect(posthog.track).not.toHaveBeenCalled();\n expect(datalayer.track).not.toHaveBeenCalled();\n expect(mixpanel.identify).not.toHaveBeenCalled();\n expect(posthog.identify).not.toHaveBeenCalled();\n expect(mixpanel.trackPageView).not.toHaveBeenCalled();\n expect(posthog.trackPageView).not.toHaveBeenCalled();\n expect(datalayer.trackPageView).not.toHaveBeenCalled();\n\n // Now initialize\n insights.initInsights(testConfig);\n\n // Initialize should be called immediately\n expect(mixpanel.initMixpanel).toHaveBeenCalledWith(\n testConfig.mixpanelToken,\n testConfig.mixpanelAutoCapture,\n testConfig.debug,\n testConfig.mixpanelRecordSessionsPercent,\n );\n expect(posthog.initPosthog).toHaveBeenCalledWith(\n testConfig.posthogApiKey,\n testConfig.posthogApiHost,\n );\n\n // Queued methods should now be called in the correct order\n expect(mixpanel.track).toHaveBeenCalledWith(\"early_event\", {\n early: true,\n });\n expect(posthog.track).toHaveBeenCalledWith(\"early_event\", {\n early: true,\n });\n expect(datalayer.track).toHaveBeenCalledWith(\"early_event\", {\n early: true,\n });\n\n expect(mixpanel.identify).toHaveBeenCalledWith(testIdentity);\n expect(posthog.identify).toHaveBeenCalledWith(testIdentity);\n\n expect(mixpanel.trackPageView).toHaveBeenCalled();\n expect(posthog.trackPageView).toHaveBeenCalled();\n expect(datalayer.trackPageView).not.toHaveBeenCalled();\n });\n\n it(\"should handle errors in queued methods gracefully\", async () => {\n // Setup an error for one of the methods\n (mixpanel.track as Mock).mockImplementationOnce(() => {\n throw new Error(\"Mixpanel error\");\n });\n\n // Call methods before initialization\n insights.track(\"error_event\", { error: true });\n insights.trackPageView();\n\n // Now initialize\n insights.initInsights(testConfig);\n\n // Should have logged the error but continued processing the queue\n expect(logger.error).toHaveBeenCalledWith(\n expect.stringContaining(\"Failed to track event in Mixpanel\"),\n expect.any(Error),\n );\n\n // The other methods should still be called\n expect(posthog.track).toHaveBeenCalledWith(\"error_event\", {\n error: true,\n });\n expect(datalayer.track).toHaveBeenCalledWith(\"error_event\", {\n error: true,\n });\n expect(mixpanel.trackPageView).toHaveBeenCalled();\n expect(posthog.trackPageView).toHaveBeenCalled();\n expect(datalayer.trackPageView).not.toHaveBeenCalled();\n });\n\n it(\"should report page view to GTM as well when includeDataLayer is true\", () => {\n insights.trackPageView({ includeDataLayer: true });\n expect(mixpanel.trackPageView).toHaveBeenCalled();\n expect(posthog.trackPageView).toHaveBeenCalled();\n expect(datalayer.trackPageView).toHaveBeenCalled();\n });\n });\n\n describe(\"Post-initialization Direct Execution\", () => {\n beforeEach(() => {\n // Initialize first\n insights.initInsights(testConfig);\n // Clear the mocks to focus on post-init behavior\n vi.clearAllMocks();\n });\n\n it(\"should directly call methods after initialization\", () => {\n // Call methods after initialization\n insights.track(\"post_init_event\", { post: true });\n\n // Should be called immediately\n expect(mixpanel.track).toHaveBeenCalledWith(\"post_init_event\", {\n post: true,\n });\n expect(posthog.track).toHaveBeenCalledWith(\"post_init_event\", {\n post: true,\n });\n expect(datalayer.track).toHaveBeenCalledWith(\"post_init_event\", {\n post: true,\n });\n });\n\n it(\"should handle all exported methods correctly\", () => {\n // Test each exported method\n insights.identify(testIdentity);\n expect(mixpanel.identify).toHaveBeenCalledWith(testIdentity);\n expect(posthog.identify).toHaveBeenCalledWith(testIdentity);\n\n insights.trackPageView();\n expect(mixpanel.trackPageView).toHaveBeenCalled();\n expect(posthog.trackPageView).toHaveBeenCalled();\n expect(datalayer.trackPageView).not.toHaveBeenCalled();\n\n insights.startSessionRecording();\n expect(mixpanel.startSessionRecording).toHaveBeenCalled();\n expect(posthog.startSessionRecording).toHaveBeenCalled();\n\n insights.stopSessionRecording();\n expect(mixpanel.stopSessionRecording).toHaveBeenCalled();\n expect(posthog.stopSessionRecording).toHaveBeenCalled();\n\n insights.enableDebugMode();\n expect(mixpanel.enableDebugMode).toHaveBeenCalled();\n expect(posthog.enableDebugMode).toHaveBeenCalled();\n\n insights.disableDebugMode();\n expect(mixpanel.disableDebugMode).toHaveBeenCalled();\n expect(posthog.disableDebugMode).toHaveBeenCalled();\n });\n\n it(\"should report page view to GTM as well when includeDataLayer is true\", () => {\n insights.trackPageView({ includeDataLayer: true });\n expect(mixpanel.trackPageView).toHaveBeenCalled();\n expect(posthog.trackPageView).toHaveBeenCalled();\n expect(datalayer.trackPageView).toHaveBeenCalled();\n });\n });\n\n describe(\"Observer Setup\", () => {\n beforeEach(() => {\n insights.initInsights(testConfig);\n vi.clearAllMocks();\n });\n\n it(\"should set up click event observer and track clicks\", () => {\n // Setup observer\n const cleanup = insights.setupObserver();\n\n // Create a test element with insight attributes\n const testElement = document.createElement(\"button\");\n testElement.setAttribute(\"data-insight-event\", \"button_clicked\");\n testElement.setAttribute(\"data-insight-button-id\", \"test-123\");\n document.body.appendChild(testElement);\n\n // Simulate click\n testElement.click();\n\n // Should track the event\n expect(mixpanel.track).toHaveBeenCalledWith(\"button_clicked\", {\n buttonId: \"test-123\",\n });\n expect(posthog.track).toHaveBeenCalledWith(\"button_clicked\", {\n buttonId: \"test-123\",\n });\n expect(datalayer.track).toHaveBeenCalledWith(\"button_clicked\", {\n buttonId: \"test-123\",\n });\n\n // Test cleanup\n cleanup();\n\n // Reset tracking mocks\n vi.clearAllMocks();\n\n // Click again - should not track\n testElement.click();\n expect(mixpanel.track).not.toHaveBeenCalled();\n });\n\n it(\"should handle nested elements correctly\", () => {\n // Setup observer\n insights.setupObserver();\n\n // Create parent element with insight attributes\n const parentElement = document.createElement(\"div\");\n parentElement.setAttribute(\"data-insight-event\", \"container_clicked\");\n parentElement.setAttribute(\n \"data-insight-container-id\",\n \"parent-container\",\n );\n\n // Create child element without insights\n const childElement = document.createElement(\"span\");\n childElement.textContent = \"Click me\";\n\n // Nest elements\n parentElement.appendChild(childElement);\n document.body.appendChild(parentElement);\n\n // Click the child element\n childElement.click();\n\n // Should find and use the parent's insight attributes\n expect(mixpanel.track).toHaveBeenCalledWith(\"container_clicked\", {\n containerId: \"parent-container\",\n });\n });\n });\n\n describe(\"Error Handling\", () => {\n it(\"should handle initialization errors gracefully\", () => {\n // Setup an error in initialization\n (mixpanel.initMixpanel as Mock).mockImplementationOnce(() => {\n throw new Error(\"Mixpanel init error\");\n });\n\n // Should not throw when initializing\n expect(() => {\n insights.initInsights(testConfig);\n }).not.toThrow();\n\n // Should log the error\n expect(logger.error).toHaveBeenCalledWith(\n expect.stringContaining(\"Failed to initialize Mixpanel\"),\n expect.any(Error),\n );\n });\n\n it(\"should handle runtime errors in methods\", () => {\n // Initialize first\n insights.initInsights(testConfig);\n vi.clearAllMocks();\n\n // Setup errors in tracking\n (mixpanel.track as Mock).mockImplementationOnce(() => {\n throw new Error(\"Mixpanel track error\");\n });\n\n (posthog.track as Mock).mockImplementationOnce(() => {\n throw new Error(\"Posthog track error\");\n });\n\n // Should not throw when tracking\n expect(() => {\n insights.track(\"error_test\", { test: true });\n }).not.toThrow();\n\n // Should log the errors\n expect(logger.error).toHaveBeenCalledWith(\n expect.stringContaining(\"Failed to track event in Mixpanel\"),\n expect.any(Error),\n );\n\n expect(logger.error).toHaveBeenCalledWith(\n expect.stringContaining(\"Failed to track event in Posthog\"),\n expect.any(Error),\n );\n\n // Should still try to track with datalayer\n expect(datalayer.track).toHaveBeenCalledWith(\"error_test\", {\n test: true,\n });\n });\n });\n\n describe(\"Debug Mode\", () => {\n it(\"should respect debug flag in config\", () => {\n // Initialize with debug: true\n insights.initInsights(testConfig);\n\n // Should log debug messages\n expect(logger.debug).toHaveBeenCalledWith(\n expect.stringContaining(\"Initializing insights\"),\n );\n\n // Clear mocks and test tracking\n vi.clearAllMocks();\n insights.track(\"debug_test\", { debug: true });\n\n // Should log info about tracking\n expect(logger.info).toHaveBeenCalledWith(\n expect.stringContaining(\"Tracking event\"),\n expect.objectContaining({\n event: \"debug_test\",\n properties: { debug: true },\n }),\n );\n });\n\n it(\"should not log debug info when debug is false\", () => {\n // Initialize with debug: false\n insights.initInsights({\n ...testConfig,\n debug: false,\n });\n\n // Clear mocks and test tracking\n vi.clearAllMocks();\n insights.track(\"no_debug_test\", { debug: false });\n\n // Should not log info about tracking\n expect(logger.info).not.toHaveBeenCalled();\n });\n });\n\n describe(\"Arbitrary Properties\", () => {\n const customPageViewProperties = {\n customProperty: \"custom-value\",\n anotherProperty: 123,\n nestedObject: { foo: \"bar\" },\n };\n\n const customPageViewPropertiesWithDataLayer = {\n customProperty: \"custom-value\",\n anotherProperty: 456,\n };\n\n const customPageViewPropertiesWithExcludeIds = {\n customProperty: \"test\",\n count: 789,\n };\n\n const customIdentityProperties = {\n customProperty: \"user-custom-value\",\n userSegment: \"premium\",\n signupDate: \"2024-01-01\",\n };\n\n const customMinimalIdentityProperties = {\n customField1: \"value1\",\n customField2: 999,\n customField3: { nested: true },\n };\n\n beforeEach(() => {\n insights.initInsights(testConfig);\n vi.clearAllMocks();\n });\n\n it(\"should pass arbitrary properties through trackPageView\", () => {\n // Call trackPageView with custom properties\n insights.trackPageView(customPageViewProperties);\n\n // Verify mixpanel received all properties\n expect(mixpanel.trackPageView).toHaveBeenCalledWith(\n customPageViewProperties,\n );\n\n // Verify posthog received all properties\n expect(posthog.trackPageView).toHaveBeenCalledWith(\n customPageViewProperties,\n );\n\n // Verify datalayer did not receive anything (includeDataLayer not set)\n expect(datalayer.trackPageView).not.toHaveBeenCalled();\n });\n\n it(\"should pass arbitrary properties through trackPageView with includeDataLayer\", () => {\n // Call trackPageView with custom properties and includeDataLayer\n insights.trackPageView({\n includeDataLayer: true,\n ...customPageViewPropertiesWithDataLayer,\n });\n\n // Verify mixpanel received custom properties (includeDataLayer filtered out)\n expect(mixpanel.trackPageView).toHaveBeenCalledWith(\n customPageViewPropertiesWithDataLayer,\n );\n\n // Verify posthog received custom properties (includeDataLayer filtered out)\n expect(posthog.trackPageView).toHaveBeenCalledWith(\n customPageViewPropertiesWithDataLayer,\n );\n\n // Verify datalayer received custom properties (includeDataLayer filtered out)\n expect(datalayer.trackPageView).toHaveBeenCalledWith(\n customPageViewPropertiesWithDataLayer,\n );\n });\n\n it(\"should pass arbitrary properties through trackPageView with excludeIds\", () => {\n const excludeIds = [\"id1\", \"id2\"];\n\n // Call trackPageView with custom properties and excludeIds\n insights.trackPageView({\n excludeIds,\n ...customPageViewPropertiesWithExcludeIds,\n });\n\n // Verify mixpanel received excludeIds and custom properties\n expect(mixpanel.trackPageView).toHaveBeenCalledWith({\n excludeIds,\n ...customPageViewPropertiesWithExcludeIds,\n });\n\n // Verify posthog received only custom properties (excludeIds filtered out)\n expect(posthog.trackPageView).toHaveBeenCalledWith(\n customPageViewPropertiesWithExcludeIds,\n );\n });\n\n it(\"should pass arbitrary properties through identify\", () => {\n const identityWithCustomProps = {\n ...testIdentity,\n ...customIdentityProperties,\n };\n\n // Call identify with custom properties\n insights.identify(identityWithCustomProps);\n\n // Verify mixpanel received all properties\n expect(mixpanel.identify).toHaveBeenCalledWith(identityWithCustomProps);\n\n // Verify posthog received all properties\n expect(posthog.identify).toHaveBeenCalledWith(identityWithCustomProps);\n });\n\n it(\"should pass arbitrary properties through identify with minimal identity\", () => {\n const minimalIdentity = {\n userId: \"minimal-user\",\n accountId: \"minimal-account\",\n ...customMinimalIdentityProperties,\n };\n\n // Call identify with only required fields plus custom properties\n insights.identify(minimalIdentity);\n\n // Verify mixpanel received all properties\n expect(mixpanel.identify).toHaveBeenCalledWith(minimalIdentity);\n\n // Verify posthog received all properties\n expect(posthog.identify).toHaveBeenCalledWith(minimalIdentity);\n });\n });\n});\n"],"names":["describe","expect","beforeEach","afterEach","it","vi","datalayer","mixpanel","posthog","logger","insights","mock","track","fn","trackPageView","initMixpanel","enableDebugMode","disableDebugMode","identify","startSessionRecording","stopSessionRecording","initPosthog","debug","info","warn","error","testConfig","mixpanelToken","mixpanelAutoCapture","mixpanelRecordSessionsPercent","posthogApiKey","posthogApiHost","testIdentity","userId","accountId","organisationId","email","name","clearAllMocks","resetModules","document","body","replaceWith","cloneNode","early","not","toHaveBeenCalled","initInsights","toHaveBeenCalledWith","mockImplementationOnce","Error","stringContaining","any","includeDataLayer","post","cleanup","setupObserver","testElement","createElement","setAttribute","appendChild","click","buttonId","parentElement","childElement","textContent","containerId","toThrow","test","objectContaining","event","properties","customPageViewProperties","customProperty","anotherProperty","nestedObject","foo","customPageViewPropertiesWithDataLayer","customPageViewPropertiesWithExcludeIds","count","customIdentityProperties","userSegment","signupDate","customMinimalIdentityProperties","customField1","customField2","customField3","nested","excludeIds","identityWithCustomProps","minimalIdentity"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- import mixpanel from"mixpanel-browser";export const initMixpanel=(token,autoCapture=false,debug=false,recordSessionsPercent=1)=>{const blockSelectors=["[ph-no-capture]",'[data-sl="mask"]'];if(!token){console.warn("Mixpanel token not provided, skipping initialization");return}mixpanel.init(token,{debug:debug,persistence:"localStorage",autocapture:autoCapture?{block_selectors:blockSelectors,capture_text_content:true}:false,track_pageview:false,record_sessions_percent:recordSessionsPercent,record_mask_text_selector:null})};export const enableDebugMode=()=>{mixpanel.set_config({debug:true})};export const disableDebugMode=()=>{mixpanel.set_config({debug:false})};export const identify=({userId,accountId,organisationId,email,name})=>{if(!userId){return}mixpanel.identify(userId.toString());if(email||name){mixpanel.people.set({$email:email,$name:name})}if(accountId){mixpanel.people.union({accounts:[accountId.toString()]})}if(organisationId){mixpanel.people.set({organization_id:[organisationId.toString()]})}};const redactUrlSegments=()=>{const pathSegments=window.location.pathname.split("/");const redactedSegments=pathSegments.map(segment=>{return/^\d+$/.test(segment)?"{redacted}":segment});const url=new URL(window.location.href);url.pathname=redactedSegments.join("/");return decodeURI(url.toString()).toLowerCase()};export const trackPageView=()=>{mixpanel.track_pageview({redacted_path:redactUrlSegments()})};export const track=(event,properties)=>{mixpanel.track(event,properties)};export const startSessionRecording=()=>{mixpanel.start_session_recording()};export const stopSessionRecording=()=>{mixpanel.stop_session_recording()};
1
+ import mixpanel from"mixpanel-browser";export const initMixpanel=(token,autoCapture=false,debug=false,recordSessionsPercent=1)=>{const blockSelectors=["[data-mask]"];if(!token){console.warn("Mixpanel token not provided, skipping initialization");return}mixpanel.init(token,{debug:debug,persistence:"localStorage",autocapture:autoCapture?{block_selectors:blockSelectors,capture_text_content:true,pageview:false}:false,track_pageview:false,record_sessions_percent:recordSessionsPercent,record_mask_text_selector:"[data-mask]"})};export const enableDebugMode=()=>{mixpanel.set_config({debug:true})};export const disableDebugMode=()=>{mixpanel.set_config({debug:false})};export const identify=({userId,accountId,organisationId,email,name,...properties})=>{if(!userId){return}mixpanel.identify(userId.toString());const peopleProperties={...properties};if(email||name){peopleProperties.$email=email;peopleProperties.$name=name}if(organisationId){peopleProperties.organization_id=[organisationId.toString()]}if(Object.keys(peopleProperties).length>0){mixpanel.people.set(peopleProperties)}if(accountId){mixpanel.people.union({accounts:[accountId.toString()]})}};const redactUrlSegments=excludeIds=>{const pathSegments=window.location.pathname.split("/");const redactedSegments=pathSegments.map(segment=>{if(/^\d+$/.test(segment)||excludeIds.some(id=>id&&id!==""&&segment===id)){return"{redacted}"}return segment});const url=new URL(window.location.href);url.pathname=redactedSegments.join("/");return decodeURI(url.toString()).toLowerCase()};export const trackPageView=properties=>{const{excludeIds,...rest}=properties??{};mixpanel.track_pageview({redacted_path:redactUrlSegments(excludeIds??[]),...rest})};export const track=(event,properties)=>{mixpanel.track(event,properties)};export const startSessionRecording=()=>{mixpanel.start_session_recording()};export const stopSessionRecording=()=>{mixpanel.stop_session_recording()};
2
2
  //# sourceMappingURL=mixpanel.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/core/insights/mixpanel.ts"],"sourcesContent":["import mixpanel from \"mixpanel-browser\";\n\nimport { InsightsIdentity } from \"./types\";\n\nexport const initMixpanel = (\n token: string,\n autoCapture: boolean = false,\n debug: boolean = false,\n recordSessionsPercent = 1,\n) => {\n const blockSelectors = [\"[ph-no-capture]\", '[data-sl=\"mask\"]'];\n if (!token) {\n console.warn(\"Mixpanel token not provided, skipping initialization\");\n return;\n }\n\n mixpanel.init(token, {\n debug: debug,\n persistence: \"localStorage\",\n autocapture: autoCapture\n ? {\n block_selectors: blockSelectors,\n capture_text_content: true,\n }\n : false,\n track_pageview: false, // We'll track page views manually\n record_sessions_percent: recordSessionsPercent,\n record_mask_text_selector: null, // Prevents all text from being masked - we have other masking configured/enabled\n });\n};\n\nexport const enableDebugMode = () => {\n mixpanel.set_config({ debug: true });\n};\n\nexport const disableDebugMode = () => {\n mixpanel.set_config({ debug: false });\n};\n\nexport const identify = ({\n userId,\n accountId,\n organisationId,\n email,\n name,\n}: InsightsIdentity) => {\n // In very rare cases we might have a user without an account, so we'll\n // let null/undefined/blank strings through on that one\n if (!userId) {\n return;\n }\n\n mixpanel.identify(userId.toString());\n\n if (email || name) {\n mixpanel.people.set({ $email: email, $name: name });\n }\n\n if (accountId) {\n mixpanel.people.union({ accounts: [accountId.toString()] });\n }\n\n if (organisationId) {\n mixpanel.people.set({ organization_id: [organisationId.toString()] });\n }\n};\n\n// Simple function to replace all digits in a URL path with {redacted},\n// purely to make reporting based on aggregates easier\nconst redactUrlSegments = () => {\n const pathSegments = window.location.pathname.split(\"/\");\n\n const redactedSegments = pathSegments.map((segment) => {\n // Check if the segment contains only digits\n return /^\\d+$/.test(segment) ? \"{redacted}\" : segment;\n });\n\n // Join the segments back together\n const url = new URL(window.location.href);\n url.pathname = redactedSegments.join(\"/\");\n\n return decodeURI(url.toString()).toLowerCase();\n};\n\nexport const trackPageView = () => {\n // Add the redacted URL to the page view event for reporting\n mixpanel.track_pageview({\n redacted_path: redactUrlSegments(),\n });\n};\n\nexport const track = (event: string, properties?: Record<string, unknown>) => {\n mixpanel.track(event, properties);\n};\n\nexport const startSessionRecording = () => {\n mixpanel.start_session_recording();\n};\n\nexport const stopSessionRecording = () => {\n mixpanel.stop_session_recording();\n};\n"],"names":["mixpanel","initMixpanel","token","autoCapture","debug","recordSessionsPercent","blockSelectors","console","warn","init","persistence","autocapture","block_selectors","capture_text_content","track_pageview","record_sessions_percent","record_mask_text_selector","enableDebugMode","set_config","disableDebugMode","identify","userId","accountId","organisationId","email","name","toString","people","set","$email","$name","union","accounts","organization_id","redactUrlSegments","pathSegments","window","location","pathname","split","redactedSegments","map","segment","test","url","URL","href","join","decodeURI","toLowerCase","trackPageView","redacted_path","track","event","properties","startSessionRecording","start_session_recording","stopSessionRecording","stop_session_recording"],"mappings":"AAAA,OAAOA,aAAc,kBAAmB,AAIxC,QAAO,MAAMC,aAAe,CAC1BC,MACAC,YAAuB,KAAK,CAC5BC,MAAiB,KAAK,CACtBC,sBAAwB,CAAC,IAEzB,MAAMC,eAAiB,CAAC,kBAAmB,mBAAmB,CAC9D,GAAI,CAACJ,MAAO,CACVK,QAAQC,IAAI,CAAC,wDACb,MACF,CAEAR,SAASS,IAAI,CAACP,MAAO,CACnBE,MAAOA,MACPM,YAAa,eACbC,YAAaR,YACT,CACES,gBAAiBN,eACjBO,qBAAsB,IACxB,EACA,MACJC,eAAgB,MAChBC,wBAAyBV,sBACzBW,0BAA2B,IAC7B,EACF,CAAE,AAEF,QAAO,MAAMC,gBAAkB,KAC7BjB,SAASkB,UAAU,CAAC,CAAEd,MAAO,IAAK,EACpC,CAAE,AAEF,QAAO,MAAMe,iBAAmB,KAC9BnB,SAASkB,UAAU,CAAC,CAAEd,MAAO,KAAM,EACrC,CAAE,AAEF,QAAO,MAAMgB,SAAW,CAAC,CACvBC,MAAM,CACNC,SAAS,CACTC,cAAc,CACdC,KAAK,CACLC,IAAI,CACa,IAGjB,GAAI,CAACJ,OAAQ,CACX,MACF,CAEArB,SAASoB,QAAQ,CAACC,OAAOK,QAAQ,IAEjC,GAAIF,OAASC,KAAM,CACjBzB,SAAS2B,MAAM,CAACC,GAAG,CAAC,CAAEC,OAAQL,MAAOM,MAAOL,IAAK,EACnD,CAEA,GAAIH,UAAW,CACbtB,SAAS2B,MAAM,CAACI,KAAK,CAAC,CAAEC,SAAU,CAACV,UAAUI,QAAQ,GAAG,AAAC,EAC3D,CAEA,GAAIH,eAAgB,CAClBvB,SAAS2B,MAAM,CAACC,GAAG,CAAC,CAAEK,gBAAiB,CAACV,eAAeG,QAAQ,GAAG,AAAC,EACrE,CACF,CAAE,CAIF,MAAMQ,kBAAoB,KACxB,MAAMC,aAAeC,OAAOC,QAAQ,CAACC,QAAQ,CAACC,KAAK,CAAC,KAEpD,MAAMC,iBAAmBL,aAAaM,GAAG,CAAC,AAACC,UAEzC,MAAO,QAAQC,IAAI,CAACD,SAAW,aAAeA,OAChD,GAGA,MAAME,IAAM,IAAIC,IAAIT,OAAOC,QAAQ,CAACS,IAAI,CACxCF,CAAAA,IAAIN,QAAQ,CAAGE,iBAAiBO,IAAI,CAAC,KAErC,OAAOC,UAAUJ,IAAIlB,QAAQ,IAAIuB,WAAW,EAC9C,CAEA,QAAO,MAAMC,cAAgB,KAE3BlD,SAASc,cAAc,CAAC,CACtBqC,cAAejB,mBACjB,EACF,CAAE,AAEF,QAAO,MAAMkB,MAAQ,CAACC,MAAeC,cACnCtD,SAASoD,KAAK,CAACC,MAAOC,WACxB,CAAE,AAEF,QAAO,MAAMC,sBAAwB,KACnCvD,SAASwD,uBAAuB,EAClC,CAAE,AAEF,QAAO,MAAMC,qBAAuB,KAClCzD,SAAS0D,sBAAsB,EACjC,CAAE"}
1
+ {"version":3,"sources":["../../../src/core/insights/mixpanel.ts"],"sourcesContent":["import mixpanel from \"mixpanel-browser\";\n\nimport { InsightsIdentity, TrackPageViewOptions } from \"./types\";\n\nexport const initMixpanel = (\n token: string,\n autoCapture: boolean = false,\n debug: boolean = false,\n recordSessionsPercent = 1,\n) => {\n const blockSelectors = [\"[data-mask]\"];\n if (!token) {\n console.warn(\"Mixpanel token not provided, skipping initialization\");\n return;\n }\n\n mixpanel.init(token, {\n debug: debug,\n persistence: \"localStorage\",\n autocapture: autoCapture\n ? {\n block_selectors: blockSelectors,\n capture_text_content: true,\n pageview: false, // We'll track page views manually\n }\n : false,\n track_pageview: false, // We'll track page views manually\n record_sessions_percent: recordSessionsPercent,\n record_mask_text_selector: \"[data-mask]\",\n });\n};\n\nexport const enableDebugMode = () => {\n mixpanel.set_config({ debug: true });\n};\n\nexport const disableDebugMode = () => {\n mixpanel.set_config({ debug: false });\n};\n\nexport const identify = ({\n userId,\n accountId,\n organisationId,\n email,\n name,\n ...properties\n}: InsightsIdentity) => {\n // In very rare cases we might have a user without an account, so we'll\n // let null/undefined/blank strings through on that one\n if (!userId) {\n return;\n }\n\n mixpanel.identify(userId.toString());\n\n const peopleProperties: Record<string, unknown> = { ...properties };\n\n if (email || name) {\n peopleProperties.$email = email;\n peopleProperties.$name = name;\n }\n\n if (organisationId) {\n peopleProperties.organization_id = [organisationId.toString()];\n }\n\n if (Object.keys(peopleProperties).length > 0) {\n mixpanel.people.set(peopleProperties);\n }\n\n if (accountId) {\n mixpanel.people.union({ accounts: [accountId.toString()] });\n }\n};\n\n// Simple function to replace all digits and IDs in a URL path with {redacted},\n// purely to make reporting based on aggregates easier\nconst redactUrlSegments = (excludeIds: string[]) => {\n const pathSegments = window.location.pathname.split(\"/\");\n\n const redactedSegments = pathSegments.map((segment) => {\n // Redact if the segment contains only digits or matches any of the excluded IDs\n if (\n /^\\d+$/.test(segment) ||\n excludeIds.some((id) => id && id !== \"\" && segment === id)\n ) {\n return \"{redacted}\";\n }\n\n return segment;\n });\n\n // Join the segments back together\n const url = new URL(window.location.href);\n url.pathname = redactedSegments.join(\"/\");\n\n return decodeURI(url.toString()).toLowerCase();\n};\n\nexport const trackPageView = (properties?: TrackPageViewOptions) => {\n const { excludeIds, ...rest } = properties ?? {};\n\n // Add the redacted URL to the page view event for reporting\n mixpanel.track_pageview({\n redacted_path: redactUrlSegments(excludeIds ?? []),\n ...rest,\n });\n};\n\nexport const track = (event: string, properties?: Record<string, unknown>) => {\n mixpanel.track(event, properties);\n};\n\nexport const startSessionRecording = () => {\n mixpanel.start_session_recording();\n};\n\nexport const stopSessionRecording = () => {\n mixpanel.stop_session_recording();\n};\n"],"names":["mixpanel","initMixpanel","token","autoCapture","debug","recordSessionsPercent","blockSelectors","console","warn","init","persistence","autocapture","block_selectors","capture_text_content","pageview","track_pageview","record_sessions_percent","record_mask_text_selector","enableDebugMode","set_config","disableDebugMode","identify","userId","accountId","organisationId","email","name","properties","toString","peopleProperties","$email","$name","organization_id","Object","keys","length","people","set","union","accounts","redactUrlSegments","excludeIds","pathSegments","window","location","pathname","split","redactedSegments","map","segment","test","some","id","url","URL","href","join","decodeURI","toLowerCase","trackPageView","rest","redacted_path","track","event","startSessionRecording","start_session_recording","stopSessionRecording","stop_session_recording"],"mappings":"AAAA,OAAOA,aAAc,kBAAmB,AAIxC,QAAO,MAAMC,aAAe,CAC1BC,MACAC,YAAuB,KAAK,CAC5BC,MAAiB,KAAK,CACtBC,sBAAwB,CAAC,IAEzB,MAAMC,eAAiB,CAAC,cAAc,CACtC,GAAI,CAACJ,MAAO,CACVK,QAAQC,IAAI,CAAC,wDACb,MACF,CAEAR,SAASS,IAAI,CAACP,MAAO,CACnBE,MAAOA,MACPM,YAAa,eACbC,YAAaR,YACT,CACES,gBAAiBN,eACjBO,qBAAsB,KACtBC,SAAU,KACZ,EACA,MACJC,eAAgB,MAChBC,wBAAyBX,sBACzBY,0BAA2B,aAC7B,EACF,CAAE,AAEF,QAAO,MAAMC,gBAAkB,KAC7BlB,SAASmB,UAAU,CAAC,CAAEf,MAAO,IAAK,EACpC,CAAE,AAEF,QAAO,MAAMgB,iBAAmB,KAC9BpB,SAASmB,UAAU,CAAC,CAAEf,MAAO,KAAM,EACrC,CAAE,AAEF,QAAO,MAAMiB,SAAW,CAAC,CACvBC,MAAM,CACNC,SAAS,CACTC,cAAc,CACdC,KAAK,CACLC,IAAI,CACJ,GAAGC,WACc,IAGjB,GAAI,CAACL,OAAQ,CACX,MACF,CAEAtB,SAASqB,QAAQ,CAACC,OAAOM,QAAQ,IAEjC,MAAMC,iBAA4C,CAAE,GAAGF,UAAU,AAAC,EAElE,GAAIF,OAASC,KAAM,CACjBG,iBAAiBC,MAAM,CAAGL,KAC1BI,CAAAA,iBAAiBE,KAAK,CAAGL,IAC3B,CAEA,GAAIF,eAAgB,CAClBK,iBAAiBG,eAAe,CAAG,CAACR,eAAeI,QAAQ,GAAG,AAChE,CAEA,GAAIK,OAAOC,IAAI,CAACL,kBAAkBM,MAAM,CAAG,EAAG,CAC5CnC,SAASoC,MAAM,CAACC,GAAG,CAACR,iBACtB,CAEA,GAAIN,UAAW,CACbvB,SAASoC,MAAM,CAACE,KAAK,CAAC,CAAEC,SAAU,CAAChB,UAAUK,QAAQ,GAAG,AAAC,EAC3D,CACF,CAAE,CAIF,MAAMY,kBAAoB,AAACC,aACzB,MAAMC,aAAeC,OAAOC,QAAQ,CAACC,QAAQ,CAACC,KAAK,CAAC,KAEpD,MAAMC,iBAAmBL,aAAaM,GAAG,CAAC,AAACC,UAEzC,GACE,QAAQC,IAAI,CAACD,UACbR,WAAWU,IAAI,CAAC,AAACC,IAAOA,IAAMA,KAAO,IAAMH,UAAYG,IACvD,CACA,MAAO,YACT,CAEA,OAAOH,OACT,GAGA,MAAMI,IAAM,IAAIC,IAAIX,OAAOC,QAAQ,CAACW,IAAI,CACxCF,CAAAA,IAAIR,QAAQ,CAAGE,iBAAiBS,IAAI,CAAC,KAErC,OAAOC,UAAUJ,IAAIzB,QAAQ,IAAI8B,WAAW,EAC9C,CAEA,QAAO,MAAMC,cAAgB,AAAChC,aAC5B,KAAM,CAAEc,UAAU,CAAE,GAAGmB,KAAM,CAAGjC,YAAc,CAAC,EAG/C3B,SAASe,cAAc,CAAC,CACtB8C,cAAerB,kBAAkBC,YAAc,EAAE,EACjD,GAAGmB,IAAI,AACT,EACF,CAAE,AAEF,QAAO,MAAME,MAAQ,CAACC,MAAepC,cACnC3B,SAAS8D,KAAK,CAACC,MAAOpC,WACxB,CAAE,AAEF,QAAO,MAAMqC,sBAAwB,KACnChE,SAASiE,uBAAuB,EAClC,CAAE,AAEF,QAAO,MAAMC,qBAAuB,KAClClE,SAASmE,sBAAsB,EACjC,CAAE"}
@@ -0,0 +1,2 @@
1
+ import{describe,expect,beforeEach,it,vi}from"vitest";import mixpanel from"mixpanel-browser";import{initMixpanel}from"./mixpanel";vi.mock("mixpanel-browser",()=>({default:{init:vi.fn()}}));describe("initMixpanel",()=>{beforeEach(()=>{vi.clearAllMocks()});it("does not initialize without a token",()=>{const consoleSpy=vi.spyOn(console,"warn").mockImplementation(()=>{});initMixpanel("");expect(mixpanel.init).not.toHaveBeenCalled();consoleSpy.mockRestore()});it("blocks [data-mask] elements in autocapture",()=>{initMixpanel("test-token",true);const config=mixpanel.init.mock.calls[0][1];expect(config.autocapture.block_selectors).toEqual(["[data-mask]"])});it("masks [data-mask] elements in session recordings",()=>{initMixpanel("test-token",true);const config=mixpanel.init.mock.calls[0][1];expect(config.record_mask_text_selector).toBe("[data-mask]")})});
2
+ //# sourceMappingURL=mixpanel.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/core/insights/mixpanel.test.ts"],"sourcesContent":["/**\n * @vitest-environment jsdom\n */\n\nimport { describe, expect, beforeEach, it, vi } from \"vitest\";\nimport mixpanel from \"mixpanel-browser\";\n\nimport { initMixpanel } from \"./mixpanel\";\n\nvi.mock(\"mixpanel-browser\", () => ({\n default: {\n init: vi.fn(),\n },\n}));\n\ndescribe(\"initMixpanel\", () => {\n beforeEach(() => {\n vi.clearAllMocks();\n });\n\n it(\"does not initialize without a token\", () => {\n const consoleSpy = vi.spyOn(console, \"warn\").mockImplementation(() => {});\n initMixpanel(\"\");\n expect(mixpanel.init).not.toHaveBeenCalled();\n consoleSpy.mockRestore();\n });\n\n it(\"blocks [data-mask] elements in autocapture\", () => {\n initMixpanel(\"test-token\", true);\n\n const config = (mixpanel.init as ReturnType<typeof vi.fn>).mock.calls[0][1];\n expect(config.autocapture.block_selectors).toEqual([\"[data-mask]\"]);\n });\n\n it(\"masks [data-mask] elements in session recordings\", () => {\n initMixpanel(\"test-token\", true);\n\n const config = (mixpanel.init as ReturnType<typeof vi.fn>).mock.calls[0][1];\n expect(config.record_mask_text_selector).toBe(\"[data-mask]\");\n });\n});\n"],"names":["describe","expect","beforeEach","it","vi","mixpanel","initMixpanel","mock","default","init","fn","clearAllMocks","consoleSpy","spyOn","console","mockImplementation","not","toHaveBeenCalled","mockRestore","config","calls","autocapture","block_selectors","toEqual","record_mask_text_selector","toBe"],"mappings":"AAIA,OAASA,QAAQ,CAAEC,MAAM,CAAEC,UAAU,CAAEC,EAAE,CAAEC,EAAE,KAAQ,QAAS,AAC9D,QAAOC,aAAc,kBAAmB,AAExC,QAASC,YAAY,KAAQ,YAAa,CAE1CF,GAAGG,IAAI,CAAC,mBAAoB,IAAO,CAAA,CACjCC,QAAS,CACPC,KAAML,GAAGM,EAAE,EACb,CACF,CAAA,GAEAV,SAAS,eAAgB,KACvBE,WAAW,KACTE,GAAGO,aAAa,EAClB,GAEAR,GAAG,sCAAuC,KACxC,MAAMS,WAAaR,GAAGS,KAAK,CAACC,QAAS,QAAQC,kBAAkB,CAAC,KAAO,GACvET,aAAa,IACbL,OAAOI,SAASI,IAAI,EAAEO,GAAG,CAACC,gBAAgB,GAC1CL,WAAWM,WAAW,EACxB,GAEAf,GAAG,6CAA8C,KAC/CG,aAAa,aAAc,MAE3B,MAAMa,OAAS,AAACd,SAASI,IAAI,CAA8BF,IAAI,CAACa,KAAK,CAAC,EAAE,CAAC,EAAE,CAC3EnB,OAAOkB,OAAOE,WAAW,CAACC,eAAe,EAAEC,OAAO,CAAC,CAAC,cAAc,CACpE,GAEApB,GAAG,mDAAoD,KACrDG,aAAa,aAAc,MAE3B,MAAMa,OAAS,AAACd,SAASI,IAAI,CAA8BF,IAAI,CAACa,KAAK,CAAC,EAAE,CAAC,EAAE,CAC3EnB,OAAOkB,OAAOK,yBAAyB,EAAEC,IAAI,CAAC,cAChD,EACF"}
@@ -1,2 +1,2 @@
1
- import posthog from"posthog-js";export const initPosthog=(apiKey,apiHost)=>{posthog.init(apiKey,{api_host:apiHost,capture_pageview:false})};export const enableDebugMode=()=>{posthog.debug()};export const disableDebugMode=()=>{posthog.debug(false)};export const identify=({userId,accountId,organisationId,email,name})=>{if(!userId){return}if(userId!==posthog.get_distinct_id()){posthog.identify(userId,{email,name})}if(accountId){posthog.group("account",accountId)}if(organisationId){posthog.group("organisation",organisationId)}};export const trackPageView=()=>{posthog.capture("$pageview")};export const track=(event,properties)=>{posthog.capture(event,properties)};export const startSessionRecording=()=>{posthog.startSessionRecording()};export const stopSessionRecording=()=>{posthog.stopSessionRecording()};
1
+ import posthog from"posthog-js";export const initPosthog=(apiKey,apiHost)=>{if(!apiKey){return}posthog.init(apiKey,{api_host:apiHost,capture_pageview:false,session_recording:{maskTextSelector:"[data-mask]"}})};export const enableDebugMode=()=>{posthog.debug()};export const disableDebugMode=()=>{posthog.debug(false)};export const identify=({userId,accountId,organisationId,email,name,...properties})=>{if(!userId){return}if(userId!==posthog.get_distinct_id()){posthog.identify(userId,{email,name,...properties})}if(accountId){posthog.group("account",accountId)}if(organisationId){posthog.group("organisation",organisationId)}};export const trackPageView=properties=>{posthog.capture("$pageview",properties)};export const track=(event,properties)=>{posthog.capture(event,properties)};export const startSessionRecording=()=>{posthog.startSessionRecording()};export const stopSessionRecording=()=>{posthog.stopSessionRecording()};
2
2
  //# sourceMappingURL=posthog.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/core/insights/posthog.ts"],"sourcesContent":["import posthog from \"posthog-js\";\n\nimport { InsightsIdentity } from \"./types\";\n\nexport const initPosthog = (apiKey: string, apiHost: string) => {\n posthog.init(apiKey, {\n api_host: apiHost,\n capture_pageview: false,\n });\n};\n\nexport const enableDebugMode = () => {\n posthog.debug();\n};\n\nexport const disableDebugMode = () => {\n posthog.debug(false);\n};\n\nexport const identify = ({\n userId,\n accountId,\n organisationId,\n email,\n name,\n}: InsightsIdentity) => {\n // In very rare cases we might have a user without an account, so we'll\n // let null/undefined/blank strings through on that one\n if (!userId) {\n return;\n }\n\n if (userId !== posthog.get_distinct_id()) {\n posthog.identify(userId, { email, name });\n }\n\n // Associate all events in this session with this account\n if (accountId) {\n posthog.group(\"account\", accountId);\n }\n\n // Associate all events in this session with this organisation (if available)\n if (organisationId) {\n posthog.group(\"organisation\", organisationId);\n }\n};\n\nexport const trackPageView = () => {\n posthog.capture(\"$pageview\");\n};\n\nexport const track = (event: string, properties?: Record<string, unknown>) => {\n posthog.capture(event, properties);\n};\n\nexport const startSessionRecording = () => {\n posthog.startSessionRecording();\n};\n\nexport const stopSessionRecording = () => {\n posthog.stopSessionRecording();\n};\n"],"names":["posthog","initPosthog","apiKey","apiHost","init","api_host","capture_pageview","enableDebugMode","debug","disableDebugMode","identify","userId","accountId","organisationId","email","name","get_distinct_id","group","trackPageView","capture","track","event","properties","startSessionRecording","stopSessionRecording"],"mappings":"AAAA,OAAOA,YAAa,YAAa,AAIjC,QAAO,MAAMC,YAAc,CAACC,OAAgBC,WAC1CH,QAAQI,IAAI,CAACF,OAAQ,CACnBG,SAAUF,QACVG,iBAAkB,KACpB,EACF,CAAE,AAEF,QAAO,MAAMC,gBAAkB,KAC7BP,QAAQQ,KAAK,EACf,CAAE,AAEF,QAAO,MAAMC,iBAAmB,KAC9BT,QAAQQ,KAAK,CAAC,MAChB,CAAE,AAEF,QAAO,MAAME,SAAW,CAAC,CACvBC,MAAM,CACNC,SAAS,CACTC,cAAc,CACdC,KAAK,CACLC,IAAI,CACa,IAGjB,GAAI,CAACJ,OAAQ,CACX,MACF,CAEA,GAAIA,SAAWX,QAAQgB,eAAe,GAAI,CACxChB,QAAQU,QAAQ,CAACC,OAAQ,CAAEG,MAAOC,IAAK,EACzC,CAGA,GAAIH,UAAW,CACbZ,QAAQiB,KAAK,CAAC,UAAWL,UAC3B,CAGA,GAAIC,eAAgB,CAClBb,QAAQiB,KAAK,CAAC,eAAgBJ,eAChC,CACF,CAAE,AAEF,QAAO,MAAMK,cAAgB,KAC3BlB,QAAQmB,OAAO,CAAC,YAClB,CAAE,AAEF,QAAO,MAAMC,MAAQ,CAACC,MAAeC,cACnCtB,QAAQmB,OAAO,CAACE,MAAOC,WACzB,CAAE,AAEF,QAAO,MAAMC,sBAAwB,KACnCvB,QAAQuB,qBAAqB,EAC/B,CAAE,AAEF,QAAO,MAAMC,qBAAuB,KAClCxB,QAAQwB,oBAAoB,EAC9B,CAAE"}
1
+ {"version":3,"sources":["../../../src/core/insights/posthog.ts"],"sourcesContent":["import posthog from \"posthog-js\";\n\nimport { InsightsIdentity } from \"./types\";\n\nexport const initPosthog = (apiKey: string, apiHost: string) => {\n if (!apiKey) {\n return;\n }\n\n posthog.init(apiKey, {\n api_host: apiHost,\n capture_pageview: false,\n session_recording: {\n maskTextSelector: \"[data-mask]\",\n },\n });\n};\n\nexport const enableDebugMode = () => {\n posthog.debug();\n};\n\nexport const disableDebugMode = () => {\n posthog.debug(false);\n};\n\nexport const identify = ({\n userId,\n accountId,\n organisationId,\n email,\n name,\n ...properties\n}: InsightsIdentity) => {\n // In very rare cases we might have a user without an account, so we'll\n // let null/undefined/blank strings through on that one\n if (!userId) {\n return;\n }\n\n if (userId !== posthog.get_distinct_id()) {\n posthog.identify(userId, { email, name, ...properties });\n }\n\n // Associate all events in this session with this account\n if (accountId) {\n posthog.group(\"account\", accountId);\n }\n\n // Associate all events in this session with this organisation (if available)\n if (organisationId) {\n posthog.group(\"organisation\", organisationId);\n }\n};\n\nexport const trackPageView = (properties?: Record<string, unknown>) => {\n posthog.capture(\"$pageview\", properties);\n};\n\nexport const track = (event: string, properties?: Record<string, unknown>) => {\n posthog.capture(event, properties);\n};\n\nexport const startSessionRecording = () => {\n posthog.startSessionRecording();\n};\n\nexport const stopSessionRecording = () => {\n posthog.stopSessionRecording();\n};\n"],"names":["posthog","initPosthog","apiKey","apiHost","init","api_host","capture_pageview","session_recording","maskTextSelector","enableDebugMode","debug","disableDebugMode","identify","userId","accountId","organisationId","email","name","properties","get_distinct_id","group","trackPageView","capture","track","event","startSessionRecording","stopSessionRecording"],"mappings":"AAAA,OAAOA,YAAa,YAAa,AAIjC,QAAO,MAAMC,YAAc,CAACC,OAAgBC,WAC1C,GAAI,CAACD,OAAQ,CACX,MACF,CAEAF,QAAQI,IAAI,CAACF,OAAQ,CACnBG,SAAUF,QACVG,iBAAkB,MAClBC,kBAAmB,CACjBC,iBAAkB,aACpB,CACF,EACF,CAAE,AAEF,QAAO,MAAMC,gBAAkB,KAC7BT,QAAQU,KAAK,EACf,CAAE,AAEF,QAAO,MAAMC,iBAAmB,KAC9BX,QAAQU,KAAK,CAAC,MAChB,CAAE,AAEF,QAAO,MAAME,SAAW,CAAC,CACvBC,MAAM,CACNC,SAAS,CACTC,cAAc,CACdC,KAAK,CACLC,IAAI,CACJ,GAAGC,WACc,IAGjB,GAAI,CAACL,OAAQ,CACX,MACF,CAEA,GAAIA,SAAWb,QAAQmB,eAAe,GAAI,CACxCnB,QAAQY,QAAQ,CAACC,OAAQ,CAAEG,MAAOC,KAAM,GAAGC,UAAU,AAAC,EACxD,CAGA,GAAIJ,UAAW,CACbd,QAAQoB,KAAK,CAAC,UAAWN,UAC3B,CAGA,GAAIC,eAAgB,CAClBf,QAAQoB,KAAK,CAAC,eAAgBL,eAChC,CACF,CAAE,AAEF,QAAO,MAAMM,cAAgB,AAACH,aAC5BlB,QAAQsB,OAAO,CAAC,YAAaJ,WAC/B,CAAE,AAEF,QAAO,MAAMK,MAAQ,CAACC,MAAeN,cACnClB,QAAQsB,OAAO,CAACE,MAAON,WACzB,CAAE,AAEF,QAAO,MAAMO,sBAAwB,KACnCzB,QAAQyB,qBAAqB,EAC/B,CAAE,AAEF,QAAO,MAAMC,qBAAuB,KAClC1B,QAAQ0B,oBAAoB,EAC9B,CAAE"}
@@ -0,0 +1,2 @@
1
+ import{describe,expect,beforeEach,it,vi}from"vitest";import posthog from"posthog-js";import{initPosthog}from"./posthog";vi.mock("posthog-js",()=>({default:{init:vi.fn()}}));describe("initPosthog",()=>{beforeEach(()=>{vi.clearAllMocks()});it("does not initialize without an API key",()=>{initPosthog("","https://app.posthog.com");expect(posthog.init).not.toHaveBeenCalled()});it("initializes with session recording masking on [data-mask]",()=>{initPosthog("phc_test","https://app.posthog.com");expect(posthog.init).toHaveBeenCalledWith("phc_test",{api_host:"https://app.posthog.com",capture_pageview:false,session_recording:{maskTextSelector:"[data-mask]"}})})});
2
+ //# sourceMappingURL=posthog.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/core/insights/posthog.test.ts"],"sourcesContent":["/**\n * @vitest-environment jsdom\n */\n\nimport { describe, expect, beforeEach, it, vi } from \"vitest\";\nimport posthog from \"posthog-js\";\n\nimport { initPosthog } from \"./posthog\";\n\nvi.mock(\"posthog-js\", () => ({\n default: {\n init: vi.fn(),\n },\n}));\n\ndescribe(\"initPosthog\", () => {\n beforeEach(() => {\n vi.clearAllMocks();\n });\n\n it(\"does not initialize without an API key\", () => {\n initPosthog(\"\", \"https://app.posthog.com\");\n expect(posthog.init).not.toHaveBeenCalled();\n });\n\n it(\"initializes with session recording masking on [data-mask]\", () => {\n initPosthog(\"phc_test\", \"https://app.posthog.com\");\n\n expect(posthog.init).toHaveBeenCalledWith(\"phc_test\", {\n api_host: \"https://app.posthog.com\",\n capture_pageview: false,\n session_recording: {\n maskTextSelector: \"[data-mask]\",\n },\n });\n });\n});\n"],"names":["describe","expect","beforeEach","it","vi","posthog","initPosthog","mock","default","init","fn","clearAllMocks","not","toHaveBeenCalled","toHaveBeenCalledWith","api_host","capture_pageview","session_recording","maskTextSelector"],"mappings":"AAIA,OAASA,QAAQ,CAAEC,MAAM,CAAEC,UAAU,CAAEC,EAAE,CAAEC,EAAE,KAAQ,QAAS,AAC9D,QAAOC,YAAa,YAAa,AAEjC,QAASC,WAAW,KAAQ,WAAY,CAExCF,GAAGG,IAAI,CAAC,aAAc,IAAO,CAAA,CAC3BC,QAAS,CACPC,KAAML,GAAGM,EAAE,EACb,CACF,CAAA,GAEAV,SAAS,cAAe,KACtBE,WAAW,KACTE,GAAGO,aAAa,EAClB,GAEAR,GAAG,yCAA0C,KAC3CG,YAAY,GAAI,2BAChBL,OAAOI,QAAQI,IAAI,EAAEG,GAAG,CAACC,gBAAgB,EAC3C,GAEAV,GAAG,4DAA6D,KAC9DG,YAAY,WAAY,2BAExBL,OAAOI,QAAQI,IAAI,EAAEK,oBAAoB,CAAC,WAAY,CACpDC,SAAU,0BACVC,iBAAkB,MAClBC,kBAAmB,CACjBC,iBAAkB,aACpB,CACF,EACF,EACF"}
@@ -1,2 +1,2 @@
1
- function _define_property(obj,key,value){if(key in obj){Object.defineProperty(obj,key,{value:value,enumerable:true,configurable:true,writable:true})}else{obj[key]=value}return obj}import*as datalayer from"./datalayer";import*as mixpanel from"./mixpanel";import*as posthog from"./posthog";import*as logger from"./logger";export class InsightsService{initInsights({mixpanelToken,mixpanelAutoCapture,mixpanelRecordSessionsPercent=1,posthogApiKey,posthogApiHost,debug=false}){this.debugMode=!!debug;if(this.debugMode){logger.debug("InsightService: Initializing insights")}try{mixpanel.initMixpanel(mixpanelToken,mixpanelAutoCapture,this.debugMode,mixpanelRecordSessionsPercent)}catch(e){if(this.debugMode){logger.error("Failed to initialize Mixpanel",e)}}try{posthog.initPosthog(posthogApiKey,posthogApiHost)}catch(e){if(this.debugMode){logger.error("Failed to initialize Posthog",e)}}}enableDebugMode(){this.debugMode=true;logger.debug("Enabling debug mode");try{mixpanel.enableDebugMode();posthog.enableDebugMode()}catch(e){logger.error("Failed to enable debug mode",e)}}disableDebugMode(){this.debugMode=false;logger.debug("Disabling debug mode");try{mixpanel.disableDebugMode();posthog.disableDebugMode()}catch(e){logger.error("Failed to disable debug mode",e)}}identify(identity){const{userId,accountId,organisationId,email,name}=identity;if(!userId){if(this.debugMode){logger.warn("User ID not provided, skipping identify")}return}if(this.debugMode){logger.info("Identifying user",{userId,accountId,organisationId,email,name})}try{mixpanel.identify({userId,accountId,organisationId,email,name})}catch(e){if(this.debugMode){logger.error("Failed to identify user in Mixpanel",e)}}try{posthog.identify({userId,accountId,organisationId,email,name})}catch(e){if(this.debugMode){logger.error("Failed to identify user in Posthog",e)}}}trackPageView(){if(this.debugMode){logger.info("Tracking page view")}try{mixpanel.trackPageView()}catch(e){if(this.debugMode){logger.error("Failed to track page view in Mixpanel",e)}}try{posthog.trackPageView()}catch(e){if(this.debugMode){logger.error("Failed to track page view in Posthog",e)}}}track(event,properties){if(this.debugMode){logger.info("Tracking event",{event,properties})}try{mixpanel.track(event,properties)}catch(e){if(this.debugMode){logger.error("Failed to track event in Mixpanel",e)}}try{posthog.track(event,properties)}catch(e){if(this.debugMode){logger.error("Failed to track event in Posthog",e)}}try{datalayer.track(event,properties)}catch(e){if(this.debugMode){logger.error("Failed to track event in Datalayer",e)}}}startSessionRecording(){if(this.debugMode){logger.info("Starting session recording")}try{mixpanel.startSessionRecording()}catch(e){if(this.debugMode){logger.error("Failed to start session recording in Mixpanel",e)}}try{posthog.startSessionRecording()}catch(e){if(this.debugMode){logger.error("Failed to start session recording in Posthog",e)}}}stopSessionRecording(){if(this.debugMode){logger.info("Stopping session recording")}try{mixpanel.stopSessionRecording()}catch(e){if(this.debugMode){logger.error("Failed to stop session recording in Mixpanel",e)}}try{posthog.stopSessionRecording()}catch(e){if(this.debugMode){logger.error("Failed to stop session recording in Posthog",e)}}}setupObserver(){const getInsightAttributes=element=>{const MAX_ATTRIBUTES=10;let count=0;const attributes={};for(const attr of element.attributes){if(count>=MAX_ATTRIBUTES)break;if(attr.name.startsWith("data-insight-")){if(!/^data-insight-[a-zA-Z0-9-]+$/.test(attr.name))continue;if(typeof attr.value!=="string"||attr.value.length>100)continue;const key=attr.name.replace("data-insight-","").split("-").map((part,index)=>index===0?part:part.charAt(0).toUpperCase()+part.slice(1)).join("");attributes[key]=attr.value;count++}}return attributes};const findClosestElementWithInsights=element=>{let current=element;while(current&&current!==document.body){const insights=getInsightAttributes(current);if(Object.keys(insights).length>0){return insights}current=current.parentElement}return null};const handleClick=event=>{if(!(event.target instanceof HTMLElement))return;const insights=findClosestElementWithInsights(event.target);if(insights){const{event:eventName,...properties}=insights;this.track(eventName||"element_clicked",properties)}};document.body.addEventListener("click",handleClick);return()=>{document.body.removeEventListener("click",handleClick)}}constructor(){_define_property(this,"debugMode",false)}}
1
+ function _define_property(obj,key,value){if(key in obj){Object.defineProperty(obj,key,{value:value,enumerable:true,configurable:true,writable:true})}else{obj[key]=value}return obj}import*as datalayer from"./datalayer";import*as mixpanel from"./mixpanel";import*as posthog from"./posthog";import*as logger from"./logger";export class InsightsService{initInsights({mixpanelToken,mixpanelAutoCapture,mixpanelRecordSessionsPercent=1,posthogApiKey,posthogApiHost,debug=false}){this.debugMode=!!debug;if(this.debugMode){logger.debug("InsightService: Initializing insights")}try{mixpanel.initMixpanel(mixpanelToken,mixpanelAutoCapture,this.debugMode,mixpanelRecordSessionsPercent)}catch(e){if(this.debugMode){logger.error("Failed to initialize Mixpanel",e)}}try{posthog.initPosthog(posthogApiKey,posthogApiHost)}catch(e){if(this.debugMode){logger.error("Failed to initialize Posthog",e)}}}enableDebugMode(){this.debugMode=true;logger.debug("Enabling debug mode");try{mixpanel.enableDebugMode();posthog.enableDebugMode()}catch(e){logger.error("Failed to enable debug mode",e)}}disableDebugMode(){this.debugMode=false;logger.debug("Disabling debug mode");try{mixpanel.disableDebugMode();posthog.disableDebugMode()}catch(e){logger.error("Failed to disable debug mode",e)}}identify(identity){const{userId,accountId,organisationId,email,name,...properties}=identity;if(!userId){if(this.debugMode){logger.warn("User ID not provided, skipping identify")}return}if(this.debugMode){logger.info("Identifying user",{userId,accountId,organisationId,email,name,...properties})}try{mixpanel.identify({userId,accountId,organisationId,email,name,...properties})}catch(e){if(this.debugMode){logger.error("Failed to identify user in Mixpanel",e)}}try{posthog.identify({userId,accountId,organisationId,email,name,...properties})}catch(e){if(this.debugMode){logger.error("Failed to identify user in Posthog",e)}}}trackPageView(options){const{excludeIds,includeDataLayer,...properties}=options??{};if(this.debugMode){logger.info("Tracking page view")}try{mixpanel.trackPageView({excludeIds,...properties})}catch(e){if(this.debugMode){logger.error("Failed to track page view in Mixpanel",e)}}try{posthog.trackPageView(properties)}catch(e){if(this.debugMode){logger.error("Failed to track page view in Posthog",e)}}if(includeDataLayer){try{datalayer.trackPageView(properties)}catch(e){if(this.debugMode){logger.error("Failed to track page view in GTM",e)}}}}track(event,properties){if(this.debugMode){logger.info("Tracking event",{event,properties})}try{mixpanel.track(event,properties)}catch(e){if(this.debugMode){logger.error("Failed to track event in Mixpanel",e)}}try{posthog.track(event,properties)}catch(e){if(this.debugMode){logger.error("Failed to track event in Posthog",e)}}try{datalayer.track(event,properties)}catch(e){if(this.debugMode){logger.error("Failed to track event in Datalayer",e)}}}startSessionRecording(){if(this.debugMode){logger.info("Starting session recording")}try{mixpanel.startSessionRecording()}catch(e){if(this.debugMode){logger.error("Failed to start session recording in Mixpanel",e)}}try{posthog.startSessionRecording()}catch(e){if(this.debugMode){logger.error("Failed to start session recording in Posthog",e)}}}stopSessionRecording(){if(this.debugMode){logger.info("Stopping session recording")}try{mixpanel.stopSessionRecording()}catch(e){if(this.debugMode){logger.error("Failed to stop session recording in Mixpanel",e)}}try{posthog.stopSessionRecording()}catch(e){if(this.debugMode){logger.error("Failed to stop session recording in Posthog",e)}}}setupObserver(){const getInsightAttributes=element=>{const MAX_ATTRIBUTES=10;let count=0;const attributes={};for(const attr of Array.from(element.attributes)){if(count>=MAX_ATTRIBUTES)break;if(attr.name.startsWith("data-insight-")){if(!/^data-insight-[a-zA-Z0-9-]+$/.test(attr.name))continue;if(typeof attr.value!=="string"||attr.value.length>100)continue;const key=attr.name.replace("data-insight-","").split("-").map((part,index)=>index===0?part:part.charAt(0).toUpperCase()+part.slice(1)).join("");attributes[key]=attr.value;count++}}return attributes};const findClosestElementWithInsights=element=>{let current=element;while(current&&current!==document.body){const insights=getInsightAttributes(current);if(Object.keys(insights).length>0){return insights}current=current.parentElement}return null};const handleClick=event=>{if(!(event.target instanceof HTMLElement))return;const insights=findClosestElementWithInsights(event.target);if(insights){const{event:eventName,...properties}=insights;this.track(eventName||"element_clicked",properties)}};document.body.addEventListener("click",handleClick);return()=>{document.body.removeEventListener("click",handleClick)}}constructor(){_define_property(this,"debugMode",false)}}
2
2
  //# sourceMappingURL=service.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/core/insights/service.ts"],"sourcesContent":["import type {\n AnalyticsService,\n InsightsConfig,\n InsightsIdentity,\n} from \"./types\";\nimport * as datalayer from \"./datalayer\";\nimport * as mixpanel from \"./mixpanel\";\nimport * as posthog from \"./posthog\";\nimport * as logger from \"./logger\";\n\n// The real implementation that will be used after initialization\nexport class InsightsService implements AnalyticsService {\n private debugMode: boolean = false;\n\n initInsights({\n mixpanelToken,\n mixpanelAutoCapture,\n mixpanelRecordSessionsPercent = 1,\n posthogApiKey,\n posthogApiHost,\n debug = false,\n }: InsightsConfig): void {\n this.debugMode = !!debug;\n\n if (this.debugMode) {\n logger.debug(\"InsightService: Initializing insights\");\n }\n\n try {\n mixpanel.initMixpanel(\n mixpanelToken,\n mixpanelAutoCapture,\n this.debugMode,\n mixpanelRecordSessionsPercent,\n );\n } catch (e) {\n if (this.debugMode) {\n logger.error(\"Failed to initialize Mixpanel\", e);\n }\n }\n\n try {\n posthog.initPosthog(posthogApiKey, posthogApiHost);\n } catch (e) {\n if (this.debugMode) {\n logger.error(\"Failed to initialize Posthog\", e);\n }\n }\n }\n\n enableDebugMode(): void {\n this.debugMode = true;\n logger.debug(\"Enabling debug mode\");\n\n try {\n mixpanel.enableDebugMode();\n posthog.enableDebugMode();\n } catch (e) {\n logger.error(\"Failed to enable debug mode\", e);\n }\n }\n\n disableDebugMode(): void {\n this.debugMode = false;\n logger.debug(\"Disabling debug mode\");\n\n try {\n mixpanel.disableDebugMode();\n posthog.disableDebugMode();\n } catch (e) {\n logger.error(\"Failed to disable debug mode\", e);\n }\n }\n\n identify(identity: InsightsIdentity): void {\n const { userId, accountId, organisationId, email, name } = identity;\n\n // In very rare cases we might have a user without an account, so we'll\n // let null/undefined/blank strings through on that one\n if (!userId) {\n if (this.debugMode) {\n logger.warn(\"User ID not provided, skipping identify\");\n }\n return;\n }\n\n if (this.debugMode) {\n logger.info(\"Identifying user\", {\n userId,\n accountId,\n organisationId,\n email,\n name,\n });\n }\n\n try {\n mixpanel.identify({ userId, accountId, organisationId, email, name });\n } catch (e) {\n if (this.debugMode) {\n logger.error(\"Failed to identify user in Mixpanel\", e);\n }\n }\n\n try {\n posthog.identify({ userId, accountId, organisationId, email, name });\n } catch (e) {\n if (this.debugMode) {\n logger.error(\"Failed to identify user in Posthog\", e);\n }\n }\n }\n\n trackPageView(): void {\n if (this.debugMode) {\n logger.info(\"Tracking page view\");\n }\n\n try {\n mixpanel.trackPageView();\n } catch (e) {\n if (this.debugMode) {\n logger.error(\"Failed to track page view in Mixpanel\", e);\n }\n }\n\n try {\n posthog.trackPageView();\n } catch (e) {\n if (this.debugMode) {\n logger.error(\"Failed to track page view in Posthog\", e);\n }\n }\n }\n\n track(event: string, properties?: Record<string, unknown>): void {\n if (this.debugMode) {\n logger.info(\"Tracking event\", { event, properties });\n }\n\n try {\n mixpanel.track(event, properties);\n } catch (e) {\n if (this.debugMode) {\n logger.error(\"Failed to track event in Mixpanel\", e);\n }\n }\n\n try {\n posthog.track(event, properties);\n } catch (e) {\n if (this.debugMode) {\n logger.error(\"Failed to track event in Posthog\", e);\n }\n }\n\n try {\n datalayer.track(event, properties);\n } catch (e) {\n if (this.debugMode) {\n logger.error(\"Failed to track event in Datalayer\", e);\n }\n }\n }\n\n startSessionRecording(): void {\n if (this.debugMode) {\n logger.info(\"Starting session recording\");\n }\n\n try {\n mixpanel.startSessionRecording();\n } catch (e) {\n if (this.debugMode) {\n logger.error(\"Failed to start session recording in Mixpanel\", e);\n }\n }\n\n try {\n posthog.startSessionRecording();\n } catch (e) {\n if (this.debugMode) {\n logger.error(\"Failed to start session recording in Posthog\", e);\n }\n }\n }\n\n stopSessionRecording(): void {\n if (this.debugMode) {\n logger.info(\"Stopping session recording\");\n }\n\n try {\n mixpanel.stopSessionRecording();\n } catch (e) {\n if (this.debugMode) {\n logger.error(\"Failed to stop session recording in Mixpanel\", e);\n }\n }\n\n try {\n posthog.stopSessionRecording();\n } catch (e) {\n if (this.debugMode) {\n logger.error(\"Failed to stop session recording in Posthog\", e);\n }\n }\n }\n\n setupObserver(): () => void {\n // Helper to get all data-insight-* attributes from an element\n const getInsightAttributes = (\n element,\n ): { event?: string; [key: string]: string | undefined } => {\n // limit how many data attributes we'll process\n const MAX_ATTRIBUTES = 10;\n let count = 0;\n\n const attributes: { event?: string; [key: string]: string | undefined } =\n {};\n\n for (const attr of element.attributes) {\n if (count >= MAX_ATTRIBUTES) break;\n if (attr.name.startsWith(\"data-insight-\")) {\n // Validate attribute name format\n if (!/^data-insight-[a-zA-Z0-9-]+$/.test(attr.name)) continue;\n\n // Sanitize attribute value\n if (typeof attr.value !== \"string\" || attr.value.length > 100)\n continue;\n\n // Convert data-insight-event-name to eventName\n const key = attr.name\n .replace(\"data-insight-\", \"\")\n .split(\"-\")\n .map((part, index) =>\n index === 0 ? part : part.charAt(0).toUpperCase() + part.slice(1),\n )\n .join(\"\");\n attributes[key] = attr.value;\n count++;\n }\n }\n return attributes;\n };\n\n // Helper to find closest element with data-insight attributes\n const findClosestElementWithInsights = (element) => {\n let current = element;\n while (current && current !== document.body) {\n const insights = getInsightAttributes(current);\n if (Object.keys(insights).length > 0) {\n return insights;\n }\n current = current.parentElement;\n }\n return null;\n };\n\n // Global click handler\n const handleClick = (event: MouseEvent): void => {\n if (!(event.target instanceof HTMLElement)) return;\n const insights = findClosestElementWithInsights(event.target);\n if (insights) {\n // Extract special properties if they exist\n const { event: eventName, ...properties } = insights;\n this.track(eventName || \"element_clicked\", properties);\n }\n };\n\n // Add listener to document body to catch all clicks\n document.body.addEventListener(\"click\", handleClick);\n\n // Return cleanup function in case it's needed\n return () => {\n document.body.removeEventListener(\"click\", handleClick);\n };\n }\n}\n"],"names":["datalayer","mixpanel","posthog","logger","InsightsService","initInsights","mixpanelToken","mixpanelAutoCapture","mixpanelRecordSessionsPercent","posthogApiKey","posthogApiHost","debug","debugMode","initMixpanel","e","error","initPosthog","enableDebugMode","disableDebugMode","identify","identity","userId","accountId","organisationId","email","name","warn","info","trackPageView","track","event","properties","startSessionRecording","stopSessionRecording","setupObserver","getInsightAttributes","element","MAX_ATTRIBUTES","count","attributes","attr","startsWith","test","value","length","key","replace","split","map","part","index","charAt","toUpperCase","slice","join","findClosestElementWithInsights","current","document","body","insights","Object","keys","parentElement","handleClick","target","HTMLElement","eventName","addEventListener","removeEventListener"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../src/core/insights/service.ts"],"sourcesContent":["import type {\n AnalyticsService,\n InsightsConfig,\n InsightsIdentity,\n TrackPageViewOptions,\n} from \"./types\";\nimport * as datalayer from \"./datalayer\";\nimport * as mixpanel from \"./mixpanel\";\nimport * as posthog from \"./posthog\";\nimport * as logger from \"./logger\";\n\n// The real implementation that will be used after initialization\nexport class InsightsService implements AnalyticsService {\n private debugMode: boolean = false;\n\n initInsights({\n mixpanelToken,\n mixpanelAutoCapture,\n mixpanelRecordSessionsPercent = 1,\n posthogApiKey,\n posthogApiHost,\n debug = false,\n }: InsightsConfig): void {\n this.debugMode = !!debug;\n\n if (this.debugMode) {\n logger.debug(\"InsightService: Initializing insights\");\n }\n\n try {\n mixpanel.initMixpanel(\n mixpanelToken,\n mixpanelAutoCapture,\n this.debugMode,\n mixpanelRecordSessionsPercent,\n );\n } catch (e) {\n if (this.debugMode) {\n logger.error(\"Failed to initialize Mixpanel\", e);\n }\n }\n\n try {\n posthog.initPosthog(posthogApiKey, posthogApiHost);\n } catch (e) {\n if (this.debugMode) {\n logger.error(\"Failed to initialize Posthog\", e);\n }\n }\n }\n\n enableDebugMode(): void {\n this.debugMode = true;\n logger.debug(\"Enabling debug mode\");\n\n try {\n mixpanel.enableDebugMode();\n posthog.enableDebugMode();\n } catch (e) {\n logger.error(\"Failed to enable debug mode\", e);\n }\n }\n\n disableDebugMode(): void {\n this.debugMode = false;\n logger.debug(\"Disabling debug mode\");\n\n try {\n mixpanel.disableDebugMode();\n posthog.disableDebugMode();\n } catch (e) {\n logger.error(\"Failed to disable debug mode\", e);\n }\n }\n\n identify(identity: InsightsIdentity): void {\n const { userId, accountId, organisationId, email, name, ...properties } =\n identity;\n\n // In very rare cases we might have a user without an account, so we'll\n // let null/undefined/blank strings through on that one\n if (!userId) {\n if (this.debugMode) {\n logger.warn(\"User ID not provided, skipping identify\");\n }\n return;\n }\n\n if (this.debugMode) {\n logger.info(\"Identifying user\", {\n userId,\n accountId,\n organisationId,\n email,\n name,\n ...properties,\n });\n }\n\n try {\n mixpanel.identify({\n userId,\n accountId,\n organisationId,\n email,\n name,\n ...properties,\n });\n } catch (e) {\n if (this.debugMode) {\n logger.error(\"Failed to identify user in Mixpanel\", e);\n }\n }\n\n try {\n posthog.identify({\n userId,\n accountId,\n organisationId,\n email,\n name,\n ...properties,\n });\n } catch (e) {\n if (this.debugMode) {\n logger.error(\"Failed to identify user in Posthog\", e);\n }\n }\n }\n\n trackPageView(options?: TrackPageViewOptions): void {\n const { excludeIds, includeDataLayer, ...properties } = options ?? {};\n\n if (this.debugMode) {\n logger.info(\"Tracking page view\");\n }\n\n try {\n mixpanel.trackPageView({ excludeIds, ...properties });\n } catch (e) {\n if (this.debugMode) {\n logger.error(\"Failed to track page view in Mixpanel\", e);\n }\n }\n\n try {\n posthog.trackPageView(properties);\n } catch (e) {\n if (this.debugMode) {\n logger.error(\"Failed to track page view in Posthog\", e);\n }\n }\n\n if (includeDataLayer) {\n try {\n datalayer.trackPageView(properties);\n } catch (e) {\n if (this.debugMode) {\n logger.error(\"Failed to track page view in GTM\", e);\n }\n }\n }\n }\n\n track(event: string, properties?: Record<string, unknown>): void {\n if (this.debugMode) {\n logger.info(\"Tracking event\", { event, properties });\n }\n\n try {\n mixpanel.track(event, properties);\n } catch (e) {\n if (this.debugMode) {\n logger.error(\"Failed to track event in Mixpanel\", e);\n }\n }\n\n try {\n posthog.track(event, properties);\n } catch (e) {\n if (this.debugMode) {\n logger.error(\"Failed to track event in Posthog\", e);\n }\n }\n\n try {\n datalayer.track(event, properties);\n } catch (e) {\n if (this.debugMode) {\n logger.error(\"Failed to track event in Datalayer\", e);\n }\n }\n }\n\n startSessionRecording(): void {\n if (this.debugMode) {\n logger.info(\"Starting session recording\");\n }\n\n try {\n mixpanel.startSessionRecording();\n } catch (e) {\n if (this.debugMode) {\n logger.error(\"Failed to start session recording in Mixpanel\", e);\n }\n }\n\n try {\n posthog.startSessionRecording();\n } catch (e) {\n if (this.debugMode) {\n logger.error(\"Failed to start session recording in Posthog\", e);\n }\n }\n }\n\n stopSessionRecording(): void {\n if (this.debugMode) {\n logger.info(\"Stopping session recording\");\n }\n\n try {\n mixpanel.stopSessionRecording();\n } catch (e) {\n if (this.debugMode) {\n logger.error(\"Failed to stop session recording in Mixpanel\", e);\n }\n }\n\n try {\n posthog.stopSessionRecording();\n } catch (e) {\n if (this.debugMode) {\n logger.error(\"Failed to stop session recording in Posthog\", e);\n }\n }\n }\n\n setupObserver(): () => void {\n // Helper to get all data-insight-* attributes from an element\n const getInsightAttributes = (\n element: HTMLElement,\n ): { event?: string; [key: string]: string | undefined } => {\n // limit how many data attributes we'll process\n const MAX_ATTRIBUTES = 10;\n let count = 0;\n\n const attributes: { event?: string; [key: string]: string | undefined } =\n {};\n\n for (const attr of Array.from(element.attributes)) {\n if (count >= MAX_ATTRIBUTES) break;\n if (attr.name.startsWith(\"data-insight-\")) {\n // Validate attribute name format\n if (!/^data-insight-[a-zA-Z0-9-]+$/.test(attr.name)) continue;\n\n // Sanitize attribute value\n if (typeof attr.value !== \"string\" || attr.value.length > 100)\n continue;\n\n // Convert data-insight-event-name to eventName\n const key = attr.name\n .replace(\"data-insight-\", \"\")\n .split(\"-\")\n .map((part: string, index: number) =>\n index === 0 ? part : part.charAt(0).toUpperCase() + part.slice(1),\n )\n .join(\"\");\n attributes[key] = attr.value;\n count++;\n }\n }\n return attributes;\n };\n\n // Helper to find closest element with data-insight attributes\n const findClosestElementWithInsights = (element: HTMLElement) => {\n let current = element;\n while (current && current !== document.body) {\n const insights = getInsightAttributes(current);\n if (Object.keys(insights).length > 0) {\n return insights;\n }\n\n current = current.parentElement as HTMLElement;\n }\n return null;\n };\n\n // Global click handler\n const handleClick = (event: MouseEvent): void => {\n if (!(event.target instanceof HTMLElement)) return;\n const insights = findClosestElementWithInsights(event.target);\n if (insights) {\n // Extract special properties if they exist\n const { event: eventName, ...properties } = insights;\n this.track(eventName || \"element_clicked\", properties);\n }\n };\n\n // Add listener to document body to catch all clicks\n document.body.addEventListener(\"click\", handleClick);\n\n // Return cleanup function in case it's needed\n return () => {\n document.body.removeEventListener(\"click\", handleClick);\n };\n }\n}\n"],"names":["datalayer","mixpanel","posthog","logger","InsightsService","initInsights","mixpanelToken","mixpanelAutoCapture","mixpanelRecordSessionsPercent","posthogApiKey","posthogApiHost","debug","debugMode","initMixpanel","e","error","initPosthog","enableDebugMode","disableDebugMode","identify","identity","userId","accountId","organisationId","email","name","properties","warn","info","trackPageView","options","excludeIds","includeDataLayer","track","event","startSessionRecording","stopSessionRecording","setupObserver","getInsightAttributes","element","MAX_ATTRIBUTES","count","attributes","attr","Array","from","startsWith","test","value","length","key","replace","split","map","part","index","charAt","toUpperCase","slice","join","findClosestElementWithInsights","current","document","body","insights","Object","keys","parentElement","handleClick","target","HTMLElement","eventName","addEventListener","removeEventListener"],"mappings":"oLAMA,UAAYA,cAAe,aAAc,AACzC,WAAYC,aAAc,YAAa,AACvC,WAAYC,YAAa,WAAY,AACrC,WAAYC,WAAY,UAAW,AAGnC,QAAO,MAAMC,gBAGXC,aAAa,CACXC,aAAa,CACbC,mBAAmB,CACnBC,8BAAgC,CAAC,CACjCC,aAAa,CACbC,cAAc,CACdC,MAAQ,KAAK,CACE,CAAQ,CACvB,IAAI,CAACC,SAAS,CAAG,CAAC,CAACD,MAEnB,GAAI,IAAI,CAACC,SAAS,CAAE,CAClBT,OAAOQ,KAAK,CAAC,wCACf,CAEA,GAAI,CACFV,SAASY,YAAY,CACnBP,cACAC,oBACA,IAAI,CAACK,SAAS,CACdJ,8BAEJ,CAAE,MAAOM,EAAG,CACV,GAAI,IAAI,CAACF,SAAS,CAAE,CAClBT,OAAOY,KAAK,CAAC,gCAAiCD,EAChD,CACF,CAEA,GAAI,CACFZ,QAAQc,WAAW,CAACP,cAAeC,eACrC,CAAE,MAAOI,EAAG,CACV,GAAI,IAAI,CAACF,SAAS,CAAE,CAClBT,OAAOY,KAAK,CAAC,+BAAgCD,EAC/C,CACF,CACF,CAEAG,iBAAwB,CACtB,IAAI,CAACL,SAAS,CAAG,KACjBT,OAAOQ,KAAK,CAAC,uBAEb,GAAI,CACFV,SAASgB,eAAe,GACxBf,QAAQe,eAAe,EACzB,CAAE,MAAOH,EAAG,CACVX,OAAOY,KAAK,CAAC,8BAA+BD,EAC9C,CACF,CAEAI,kBAAyB,CACvB,IAAI,CAACN,SAAS,CAAG,MACjBT,OAAOQ,KAAK,CAAC,wBAEb,GAAI,CACFV,SAASiB,gBAAgB,GACzBhB,QAAQgB,gBAAgB,EAC1B,CAAE,MAAOJ,EAAG,CACVX,OAAOY,KAAK,CAAC,+BAAgCD,EAC/C,CACF,CAEAK,SAASC,QAA0B,CAAQ,CACzC,KAAM,CAAEC,MAAM,CAAEC,SAAS,CAAEC,cAAc,CAAEC,KAAK,CAAEC,IAAI,CAAE,GAAGC,WAAY,CACrEN,SAIF,GAAI,CAACC,OAAQ,CACX,GAAI,IAAI,CAACT,SAAS,CAAE,CAClBT,OAAOwB,IAAI,CAAC,0CACd,CACA,MACF,CAEA,GAAI,IAAI,CAACf,SAAS,CAAE,CAClBT,OAAOyB,IAAI,CAAC,mBAAoB,CAC9BP,OACAC,UACAC,eACAC,MACAC,KACA,GAAGC,UAAU,AACf,EACF,CAEA,GAAI,CACFzB,SAASkB,QAAQ,CAAC,CAChBE,OACAC,UACAC,eACAC,MACAC,KACA,GAAGC,UAAU,AACf,EACF,CAAE,MAAOZ,EAAG,CACV,GAAI,IAAI,CAACF,SAAS,CAAE,CAClBT,OAAOY,KAAK,CAAC,sCAAuCD,EACtD,CACF,CAEA,GAAI,CACFZ,QAAQiB,QAAQ,CAAC,CACfE,OACAC,UACAC,eACAC,MACAC,KACA,GAAGC,UAAU,AACf,EACF,CAAE,MAAOZ,EAAG,CACV,GAAI,IAAI,CAACF,SAAS,CAAE,CAClBT,OAAOY,KAAK,CAAC,qCAAsCD,EACrD,CACF,CACF,CAEAe,cAAcC,OAA8B,CAAQ,CAClD,KAAM,CAAEC,UAAU,CAAEC,gBAAgB,CAAE,GAAGN,WAAY,CAAGI,SAAW,CAAC,EAEpE,GAAI,IAAI,CAAClB,SAAS,CAAE,CAClBT,OAAOyB,IAAI,CAAC,qBACd,CAEA,GAAI,CACF3B,SAAS4B,aAAa,CAAC,CAAEE,WAAY,GAAGL,UAAU,AAAC,EACrD,CAAE,MAAOZ,EAAG,CACV,GAAI,IAAI,CAACF,SAAS,CAAE,CAClBT,OAAOY,KAAK,CAAC,wCAAyCD,EACxD,CACF,CAEA,GAAI,CACFZ,QAAQ2B,aAAa,CAACH,WACxB,CAAE,MAAOZ,EAAG,CACV,GAAI,IAAI,CAACF,SAAS,CAAE,CAClBT,OAAOY,KAAK,CAAC,uCAAwCD,EACvD,CACF,CAEA,GAAIkB,iBAAkB,CACpB,GAAI,CACFhC,UAAU6B,aAAa,CAACH,WAC1B,CAAE,MAAOZ,EAAG,CACV,GAAI,IAAI,CAACF,SAAS,CAAE,CAClBT,OAAOY,KAAK,CAAC,mCAAoCD,EACnD,CACF,CACF,CACF,CAEAmB,MAAMC,KAAa,CAAER,UAAoC,CAAQ,CAC/D,GAAI,IAAI,CAACd,SAAS,CAAE,CAClBT,OAAOyB,IAAI,CAAC,iBAAkB,CAAEM,MAAOR,UAAW,EACpD,CAEA,GAAI,CACFzB,SAASgC,KAAK,CAACC,MAAOR,WACxB,CAAE,MAAOZ,EAAG,CACV,GAAI,IAAI,CAACF,SAAS,CAAE,CAClBT,OAAOY,KAAK,CAAC,oCAAqCD,EACpD,CACF,CAEA,GAAI,CACFZ,QAAQ+B,KAAK,CAACC,MAAOR,WACvB,CAAE,MAAOZ,EAAG,CACV,GAAI,IAAI,CAACF,SAAS,CAAE,CAClBT,OAAOY,KAAK,CAAC,mCAAoCD,EACnD,CACF,CAEA,GAAI,CACFd,UAAUiC,KAAK,CAACC,MAAOR,WACzB,CAAE,MAAOZ,EAAG,CACV,GAAI,IAAI,CAACF,SAAS,CAAE,CAClBT,OAAOY,KAAK,CAAC,qCAAsCD,EACrD,CACF,CACF,CAEAqB,uBAA8B,CAC5B,GAAI,IAAI,CAACvB,SAAS,CAAE,CAClBT,OAAOyB,IAAI,CAAC,6BACd,CAEA,GAAI,CACF3B,SAASkC,qBAAqB,EAChC,CAAE,MAAOrB,EAAG,CACV,GAAI,IAAI,CAACF,SAAS,CAAE,CAClBT,OAAOY,KAAK,CAAC,gDAAiDD,EAChE,CACF,CAEA,GAAI,CACFZ,QAAQiC,qBAAqB,EAC/B,CAAE,MAAOrB,EAAG,CACV,GAAI,IAAI,CAACF,SAAS,CAAE,CAClBT,OAAOY,KAAK,CAAC,+CAAgDD,EAC/D,CACF,CACF,CAEAsB,sBAA6B,CAC3B,GAAI,IAAI,CAACxB,SAAS,CAAE,CAClBT,OAAOyB,IAAI,CAAC,6BACd,CAEA,GAAI,CACF3B,SAASmC,oBAAoB,EAC/B,CAAE,MAAOtB,EAAG,CACV,GAAI,IAAI,CAACF,SAAS,CAAE,CAClBT,OAAOY,KAAK,CAAC,+CAAgDD,EAC/D,CACF,CAEA,GAAI,CACFZ,QAAQkC,oBAAoB,EAC9B,CAAE,MAAOtB,EAAG,CACV,GAAI,IAAI,CAACF,SAAS,CAAE,CAClBT,OAAOY,KAAK,CAAC,8CAA+CD,EAC9D,CACF,CACF,CAEAuB,eAA4B,CAE1B,MAAMC,qBAAuB,AAC3BC,UAGA,MAAMC,eAAiB,GACvB,IAAIC,MAAQ,EAEZ,MAAMC,WACJ,CAAC,EAEH,IAAK,MAAMC,QAAQC,MAAMC,IAAI,CAACN,QAAQG,UAAU,EAAG,CACjD,GAAID,OAASD,eAAgB,MAC7B,GAAIG,KAAKlB,IAAI,CAACqB,UAAU,CAAC,iBAAkB,CAEzC,GAAI,CAAC,+BAA+BC,IAAI,CAACJ,KAAKlB,IAAI,EAAG,SAGrD,GAAI,OAAOkB,KAAKK,KAAK,GAAK,UAAYL,KAAKK,KAAK,CAACC,MAAM,CAAG,IACxD,SAGF,MAAMC,IAAMP,KAAKlB,IAAI,CAClB0B,OAAO,CAAC,gBAAiB,IACzBC,KAAK,CAAC,KACNC,GAAG,CAAC,CAACC,KAAcC,QAClBA,QAAU,EAAID,KAAOA,KAAKE,MAAM,CAAC,GAAGC,WAAW,GAAKH,KAAKI,KAAK,CAAC,IAEhEC,IAAI,CAAC,GACRjB,CAAAA,UAAU,CAACQ,IAAI,CAAGP,KAAKK,KAAK,AAC5BP,CAAAA,OACF,CACF,CACA,OAAOC,UACT,EAGA,MAAMkB,+BAAiC,AAACrB,UACtC,IAAIsB,QAAUtB,QACd,MAAOsB,SAAWA,UAAYC,SAASC,IAAI,CAAE,CAC3C,MAAMC,SAAW1B,qBAAqBuB,SACtC,GAAII,OAAOC,IAAI,CAACF,UAAUf,MAAM,CAAG,EAAG,CACpC,OAAOe,QACT,CAEAH,QAAUA,QAAQM,aAAa,AACjC,CACA,OAAO,IACT,EAGA,MAAMC,YAAc,AAAClC,QACnB,GAAI,CAAEA,CAAAA,MAAMmC,MAAM,YAAYC,WAAU,EAAI,OAC5C,MAAMN,SAAWJ,+BAA+B1B,MAAMmC,MAAM,EAC5D,GAAIL,SAAU,CAEZ,KAAM,CAAE9B,MAAOqC,SAAS,CAAE,GAAG7C,WAAY,CAAGsC,SAC5C,IAAI,CAAC/B,KAAK,CAACsC,WAAa,kBAAmB7C,WAC7C,CACF,EAGAoC,SAASC,IAAI,CAACS,gBAAgB,CAAC,QAASJ,aAGxC,MAAO,KACLN,SAASC,IAAI,CAACU,mBAAmB,CAAC,QAASL,YAC7C,CACF,eAtSA,sBAAQxD,YAAqB,OAuS/B"}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/core/insights/types.ts"],"sourcesContent":["export type InsightsConfig = {\n debug: boolean;\n mixpanelToken: string;\n mixpanelAutoCapture: boolean;\n mixpanelRecordSessionsPercent: number;\n posthogApiKey: string;\n posthogApiHost: string;\n};\n\n// Define the interface for our analytics service\nexport interface AnalyticsService {\n initInsights: (config: InsightsConfig) => void;\n enableDebugMode: () => void;\n disableDebugMode: () => void;\n identify: (identity: InsightsIdentity) => void;\n trackPageView: () => void;\n track: (event: string, properties?: Record<string, unknown>) => void;\n startSessionRecording: () => void;\n stopSessionRecording: () => void;\n setupObserver: () => () => void;\n}\n\n// Command type for our queue\nexport type Command = {\n methodName: keyof AnalyticsService;\n args: unknown[];\n};\n\nexport type InsightsIdentity = {\n userId: string;\n accountId: string;\n organisationId?: string;\n email?: string;\n name?: string;\n};\n"],"names":[],"mappings":"AA4BA,QAME"}
1
+ {"version":3,"sources":["../../../src/core/insights/types.ts"],"sourcesContent":["export type InsightsConfig = {\n debug: boolean;\n mixpanelToken: string;\n mixpanelAutoCapture: boolean;\n mixpanelRecordSessionsPercent: number;\n posthogApiKey: string;\n posthogApiHost: string;\n};\n\n// Define the interface for our analytics service\nexport interface AnalyticsService {\n initInsights: (config: InsightsConfig) => void;\n enableDebugMode: () => void;\n disableDebugMode: () => void;\n identify: (identity: InsightsIdentity) => void;\n trackPageView: (options?: TrackPageViewOptions) => void;\n track: (event: string, properties?: Record<string, unknown>) => void;\n startSessionRecording: () => void;\n stopSessionRecording: () => void;\n setupObserver: () => () => void;\n}\n\n// Command type for our queue\nexport type Command = {\n methodName: keyof AnalyticsService;\n args: unknown[];\n};\n\nexport type InsightsIdentity = {\n userId: string;\n accountId: string;\n organisationId?: string;\n email?: string;\n name?: string;\n} & Record<string, unknown>;\n\nexport type TrackPageViewOptions = {\n includeDataLayer?: boolean;\n excludeIds?: string[];\n} & Record<string, unknown>;\n"],"names":[],"mappings":"AAoCA,QAG4B"}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/core/react-renderer.tsx"],"sourcesContent":["import React from \"react\";\nimport { createRoot } from \"react-dom/client\";\n\nconst renderComponent = (Component, props, node) => {\n const root = createRoot(node);\n root.render(<Component {...props} />);\n};\n\nexport { renderComponent };\n\nexport default function reactRenderer(components) {\n const reactComponents = document.querySelectorAll(\"[data-react]\");\n\n Array.from(reactComponents).forEach((node) => {\n const className = node.getAttribute(\"data-react\") ?? \"\";\n const Constructor = components[className];\n\n if (!Constructor) return;\n\n const propsJson = node.getAttribute(\"data-react-props\");\n const props = propsJson && JSON.parse(propsJson || \"\");\n\n const root = createRoot(node);\n root.render(<Constructor {...props} />);\n\n node.removeAttribute(\"data-react\");\n node.removeAttribute(\"data-react-props\");\n });\n}\n"],"names":["React","createRoot","renderComponent","Component","props","node","root","render","reactRenderer","components","reactComponents","document","querySelectorAll","Array","from","forEach","className","getAttribute","Constructor","propsJson","JSON","parse","removeAttribute"],"mappings":"AAAA,OAAOA,UAAW,OAAQ,AAC1B,QAASC,UAAU,KAAQ,kBAAmB,CAE9C,MAAMC,gBAAkB,CAACC,UAAWC,MAAOC,QACzC,MAAMC,KAAOL,WAAWI,MACxBC,KAAKC,MAAM,CAAC,oBAACJ,UAAcC,OAC7B,CAEA,QAASF,eAAe,CAAG,AAE3B,gBAAe,SAASM,cAAcC,UAAU,EAC9C,MAAMC,gBAAkBC,SAASC,gBAAgB,CAAC,gBAElDC,MAAMC,IAAI,CAACJ,iBAAiBK,OAAO,CAAC,AAACV,OACnC,MAAMW,UAAYX,KAAKY,YAAY,CAAC,eAAiB,GACrD,MAAMC,YAAcT,UAAU,CAACO,UAAU,CAEzC,GAAI,CAACE,YAAa,OAElB,MAAMC,UAAYd,KAAKY,YAAY,CAAC,oBACpC,MAAMb,MAAQe,WAAaC,KAAKC,KAAK,CAACF,WAAa,IAEnD,MAAMb,KAAOL,WAAWI,MACxBC,KAAKC,MAAM,CAAC,oBAACW,YAAgBd,QAE7BC,KAAKiB,eAAe,CAAC,cACrBjB,KAAKiB,eAAe,CAAC,mBACvB,EACF"}
1
+ {"version":3,"sources":["../../src/core/react-renderer.tsx"],"sourcesContent":["import React from \"react\";\nimport { createRoot } from \"react-dom/client\";\n\nconst renderComponent = (\n Component: React.FC,\n props: React.ComponentProps<React.FC>,\n node: HTMLElement,\n) => {\n const root = createRoot(node);\n root.render(<Component {...props} />);\n};\n\nexport { renderComponent };\n\nexport default function reactRenderer(components: Record<string, React.FC>) {\n const reactComponents = document.querySelectorAll(\"[data-react]\");\n\n Array.from(reactComponents).forEach((node) => {\n const className = node.getAttribute(\"data-react\") ?? \"\";\n const Constructor = components[className];\n\n if (!Constructor) return;\n\n const propsJson = node.getAttribute(\"data-react-props\");\n const props = propsJson && JSON.parse(propsJson || \"\");\n\n const root = createRoot(node);\n root.render(<Constructor {...props} />);\n\n node.removeAttribute(\"data-react\");\n node.removeAttribute(\"data-react-props\");\n });\n}\n"],"names":["React","createRoot","renderComponent","Component","props","node","root","render","reactRenderer","components","reactComponents","document","querySelectorAll","Array","from","forEach","className","getAttribute","Constructor","propsJson","JSON","parse","removeAttribute"],"mappings":"AAAA,OAAOA,UAAW,OAAQ,AAC1B,QAASC,UAAU,KAAQ,kBAAmB,CAE9C,MAAMC,gBAAkB,CACtBC,UACAC,MACAC,QAEA,MAAMC,KAAOL,WAAWI,MACxBC,KAAKC,MAAM,CAAC,oBAACJ,UAAcC,OAC7B,CAEA,QAASF,eAAe,CAAG,AAE3B,gBAAe,SAASM,cAAcC,UAAoC,EACxE,MAAMC,gBAAkBC,SAASC,gBAAgB,CAAC,gBAElDC,MAAMC,IAAI,CAACJ,iBAAiBK,OAAO,CAAC,AAACV,OACnC,MAAMW,UAAYX,KAAKY,YAAY,CAAC,eAAiB,GACrD,MAAMC,YAAcT,UAAU,CAACO,UAAU,CAEzC,GAAI,CAACE,YAAa,OAElB,MAAMC,UAAYd,KAAKY,YAAY,CAAC,oBACpC,MAAMb,MAAQe,WAAaC,KAAKC,KAAK,CAACF,WAAa,IAEnD,MAAMb,KAAOL,WAAWI,MACxBC,KAAKC,MAAM,CAAC,oBAACW,YAAgBd,QAE7BC,KAAKiB,eAAe,CAAC,cACrBjB,KAAKiB,eAAe,CAAC,mBACvB,EACF"}