@jmartins-tillster/analytics-react-native 2.21.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 (602) hide show
  1. package/.editorconfig +10 -0
  2. package/.eslintignore +11 -0
  3. package/.eslintrc.js +60 -0
  4. package/.gitattributes +4 -0
  5. package/.github/ISSUE_TEMPLATE/BUG_REPORT.md +23 -0
  6. package/.github/ISSUE_TEMPLATE/FEATURE_REQUEST.md +18 -0
  7. package/.github/workflows/ci.yml +158 -0
  8. package/.github/workflows/create_jira.yml +41 -0
  9. package/.github/workflows/publish.yml +57 -0
  10. package/.husky/commit-msg +4 -0
  11. package/.husky/pre-commit +4 -0
  12. package/.prettierrc.js +7 -0
  13. package/.yarnrc.yml +2 -0
  14. package/CODE_OF_CONDUCT.md +84 -0
  15. package/CONTRIBUTING.md +141 -0
  16. package/LICENSE +21 -0
  17. package/MIGRATION_GUIDE.md +185 -0
  18. package/README.md +944 -0
  19. package/babel.config.js +3 -0
  20. package/commitlint.config.js +13 -0
  21. package/examples/AnalyticsReactNativeExample/.bundle/config +2 -0
  22. package/examples/AnalyticsReactNativeExample/.eslintrc.js +4 -0
  23. package/examples/AnalyticsReactNativeExample/.prettierrc.js +7 -0
  24. package/examples/AnalyticsReactNativeExample/.watchmanconfig +1 -0
  25. package/examples/AnalyticsReactNativeExample/App.tsx +164 -0
  26. package/examples/AnalyticsReactNativeExample/Gemfile +9 -0
  27. package/examples/AnalyticsReactNativeExample/Gemfile.lock +106 -0
  28. package/examples/AnalyticsReactNativeExample/Home.tsx +206 -0
  29. package/examples/AnalyticsReactNativeExample/Modal.tsx +25 -0
  30. package/examples/AnalyticsReactNativeExample/README.md +79 -0
  31. package/examples/AnalyticsReactNativeExample/SecondPage.tsx +25 -0
  32. package/examples/AnalyticsReactNativeExample/android/app/build.gradle +119 -0
  33. package/examples/AnalyticsReactNativeExample/android/app/debug.keystore +0 -0
  34. package/examples/AnalyticsReactNativeExample/android/app/proguard-rules.pro +10 -0
  35. package/examples/AnalyticsReactNativeExample/android/app/src/debug/AndroidManifest.xml +9 -0
  36. package/examples/AnalyticsReactNativeExample/android/app/src/main/AndroidManifest.xml +26 -0
  37. package/examples/AnalyticsReactNativeExample/android/app/src/main/java/com/analyticsreactnativeexample/MainActivity.kt +22 -0
  38. package/examples/AnalyticsReactNativeExample/android/app/src/main/java/com/analyticsreactnativeexample/MainApplication.kt +44 -0
  39. package/examples/AnalyticsReactNativeExample/android/app/src/main/res/drawable/rn_edit_text_material.xml +37 -0
  40. package/examples/AnalyticsReactNativeExample/android/app/src/main/res/mipmap-hdpi/ic_launcher.png +0 -0
  41. package/examples/AnalyticsReactNativeExample/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png +0 -0
  42. package/examples/AnalyticsReactNativeExample/android/app/src/main/res/mipmap-mdpi/ic_launcher.png +0 -0
  43. package/examples/AnalyticsReactNativeExample/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png +0 -0
  44. package/examples/AnalyticsReactNativeExample/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png +0 -0
  45. package/examples/AnalyticsReactNativeExample/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png +0 -0
  46. package/examples/AnalyticsReactNativeExample/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png +0 -0
  47. package/examples/AnalyticsReactNativeExample/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png +0 -0
  48. package/examples/AnalyticsReactNativeExample/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png +0 -0
  49. package/examples/AnalyticsReactNativeExample/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png +0 -0
  50. package/examples/AnalyticsReactNativeExample/android/app/src/main/res/values/strings.xml +3 -0
  51. package/examples/AnalyticsReactNativeExample/android/app/src/main/res/values/styles.xml +9 -0
  52. package/examples/AnalyticsReactNativeExample/android/build.gradle +21 -0
  53. package/examples/AnalyticsReactNativeExample/android/gradle/wrapper/gradle-wrapper.jar +0 -0
  54. package/examples/AnalyticsReactNativeExample/android/gradle/wrapper/gradle-wrapper.properties +8 -0
  55. package/examples/AnalyticsReactNativeExample/android/gradle.properties +39 -0
  56. package/examples/AnalyticsReactNativeExample/android/gradlew +252 -0
  57. package/examples/AnalyticsReactNativeExample/android/gradlew.bat +94 -0
  58. package/examples/AnalyticsReactNativeExample/android/settings.gradle +6 -0
  59. package/examples/AnalyticsReactNativeExample/app.json +4 -0
  60. package/examples/AnalyticsReactNativeExample/babel.config.js +3 -0
  61. package/examples/AnalyticsReactNativeExample/index.js +9 -0
  62. package/examples/AnalyticsReactNativeExample/ios/.xcode.env +11 -0
  63. package/examples/AnalyticsReactNativeExample/ios/AnalyticsReactNativeExample/AppDelegate.h +6 -0
  64. package/examples/AnalyticsReactNativeExample/ios/AnalyticsReactNativeExample/AppDelegate.mm +31 -0
  65. package/examples/AnalyticsReactNativeExample/ios/AnalyticsReactNativeExample/Images.xcassets/AppIcon.appiconset/Contents.json +53 -0
  66. package/examples/AnalyticsReactNativeExample/ios/AnalyticsReactNativeExample/Images.xcassets/Contents.json +6 -0
  67. package/examples/AnalyticsReactNativeExample/ios/AnalyticsReactNativeExample/Info.plist +52 -0
  68. package/examples/AnalyticsReactNativeExample/ios/AnalyticsReactNativeExample/LaunchScreen.storyboard +47 -0
  69. package/examples/AnalyticsReactNativeExample/ios/AnalyticsReactNativeExample/PrivacyInfo.xcprivacy +37 -0
  70. package/examples/AnalyticsReactNativeExample/ios/AnalyticsReactNativeExample/main.m +10 -0
  71. package/examples/AnalyticsReactNativeExample/ios/AnalyticsReactNativeExample.xcodeproj/project.pbxproj +705 -0
  72. package/examples/AnalyticsReactNativeExample/ios/AnalyticsReactNativeExample.xcodeproj/xcshareddata/xcschemes/AnalyticsReactNativeExample.xcscheme +88 -0
  73. package/examples/AnalyticsReactNativeExample/ios/AnalyticsReactNativeExample.xcworkspace/contents.xcworkspacedata +10 -0
  74. package/examples/AnalyticsReactNativeExample/ios/AnalyticsReactNativeExample.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +8 -0
  75. package/examples/AnalyticsReactNativeExample/ios/AnalyticsReactNativeExampleTests/AnalyticsReactNativeExampleTests.m +66 -0
  76. package/examples/AnalyticsReactNativeExample/ios/AnalyticsReactNativeExampleTests/Info.plist +24 -0
  77. package/examples/AnalyticsReactNativeExample/ios/Podfile +40 -0
  78. package/examples/AnalyticsReactNativeExample/ios/Podfile.lock +1961 -0
  79. package/examples/AnalyticsReactNativeExample/metro.config.js +11 -0
  80. package/examples/AnalyticsReactNativeExample/package.json +55 -0
  81. package/examples/AnalyticsReactNativeExample/plugins/ConsentManager.tsx +75 -0
  82. package/examples/AnalyticsReactNativeExample/plugins/Logger.ts +16 -0
  83. package/examples/AnalyticsReactNativeExample/react-native.config.js +9 -0
  84. package/examples/AnalyticsReactNativeExample/tsconfig.json +3 -0
  85. package/examples/AnalyticsReactNativeExample/workspace.js +5 -0
  86. package/examples/AnalyticsReactNativeExample/yarn.lock +11110 -0
  87. package/examples/E2E/.bundle/config +2 -0
  88. package/examples/E2E/.detoxrc.js +96 -0
  89. package/examples/E2E/.mise.toml +5 -0
  90. package/examples/E2E/.prettierrc.js +7 -0
  91. package/examples/E2E/.watchmanconfig +1 -0
  92. package/examples/E2E/App.tsx +176 -0
  93. package/examples/E2E/Gemfile +7 -0
  94. package/examples/E2E/Gemfile.lock +101 -0
  95. package/examples/E2E/Home.tsx +206 -0
  96. package/examples/E2E/Modal.tsx +25 -0
  97. package/examples/E2E/README.md +79 -0
  98. package/examples/E2E/SecondPage.tsx +25 -0
  99. package/examples/E2E/android/app/build.gradle +128 -0
  100. package/examples/E2E/android/app/debug.keystore +0 -0
  101. package/examples/E2E/android/app/proguard-rules.pro +10 -0
  102. package/examples/E2E/android/app/src/androidTest/java/com/segmentanalyticsreactnativeexample/DetoxTest.java +29 -0
  103. package/examples/E2E/android/app/src/debug/AndroidManifest.xml +13 -0
  104. package/examples/E2E/android/app/src/debug/java/com/analyticsreactnativeexample/ReactNativeFlipper.java +75 -0
  105. package/examples/E2E/android/app/src/main/AndroidManifest.xml +26 -0
  106. package/examples/E2E/android/app/src/main/java/com/analyticsreactnativeexample/MainActivity.java +32 -0
  107. package/examples/E2E/android/app/src/main/java/com/analyticsreactnativeexample/MainApplication.java +62 -0
  108. package/examples/E2E/android/app/src/main/res/drawable/rn_edit_text_material.xml +36 -0
  109. package/examples/E2E/android/app/src/main/res/mipmap-hdpi/ic_launcher.png +0 -0
  110. package/examples/E2E/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png +0 -0
  111. package/examples/E2E/android/app/src/main/res/mipmap-mdpi/ic_launcher.png +0 -0
  112. package/examples/E2E/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png +0 -0
  113. package/examples/E2E/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png +0 -0
  114. package/examples/E2E/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png +0 -0
  115. package/examples/E2E/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png +0 -0
  116. package/examples/E2E/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png +0 -0
  117. package/examples/E2E/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png +0 -0
  118. package/examples/E2E/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png +0 -0
  119. package/examples/E2E/android/app/src/main/res/values/strings.xml +3 -0
  120. package/examples/E2E/android/app/src/main/res/values/styles.xml +9 -0
  121. package/examples/E2E/android/app/src/main/res/xml/network_security_config.xml +7 -0
  122. package/examples/E2E/android/app/src/release/java/com/analyticsreactnativeexample/ReactNativeFlipper.java +20 -0
  123. package/examples/E2E/android/build.gradle +37 -0
  124. package/examples/E2E/android/gradle/wrapper/gradle-wrapper.jar +0 -0
  125. package/examples/E2E/android/gradle/wrapper/gradle-wrapper.properties +6 -0
  126. package/examples/E2E/android/gradle.properties +44 -0
  127. package/examples/E2E/android/gradlew +244 -0
  128. package/examples/E2E/android/gradlew.bat +92 -0
  129. package/examples/E2E/android/settings.gradle +4 -0
  130. package/examples/E2E/app.json +4 -0
  131. package/examples/E2E/babel.config.js +14 -0
  132. package/examples/E2E/e2e/jest.config.js +13 -0
  133. package/examples/E2E/e2e/main.e2e.js +192 -0
  134. package/examples/E2E/e2e/matchers.js +34 -0
  135. package/examples/E2E/e2e/mockServer.js +56 -0
  136. package/examples/E2E/index.js +11 -0
  137. package/examples/E2E/ios/.xcode.env +11 -0
  138. package/examples/E2E/ios/AnalyticsReactNativeE2E/AppDelegate.h +6 -0
  139. package/examples/E2E/ios/AnalyticsReactNativeE2E/AppDelegate.mm +26 -0
  140. package/examples/E2E/ios/AnalyticsReactNativeE2E/Images.xcassets/AppIcon.appiconset/Contents.json +53 -0
  141. package/examples/E2E/ios/AnalyticsReactNativeE2E/Images.xcassets/Contents.json +6 -0
  142. package/examples/E2E/ios/AnalyticsReactNativeE2E/Info.plist +55 -0
  143. package/examples/E2E/ios/AnalyticsReactNativeE2E/LaunchScreen.storyboard +47 -0
  144. package/examples/E2E/ios/AnalyticsReactNativeE2E/main.m +10 -0
  145. package/examples/E2E/ios/AnalyticsReactNativeE2E.xcodeproj/project.pbxproj +721 -0
  146. package/examples/E2E/ios/AnalyticsReactNativeE2E.xcworkspace/contents.xcworkspacedata +10 -0
  147. package/examples/E2E/ios/AnalyticsReactNativeE2E.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +8 -0
  148. package/examples/E2E/ios/AnalyticsReactNativeE2ETests/AnalyticsReactNativeExampleTests.m +66 -0
  149. package/examples/E2E/ios/AnalyticsReactNativeE2ETests/Info.plist +24 -0
  150. package/examples/E2E/ios/Podfile +62 -0
  151. package/examples/E2E/ios/Podfile.lock +763 -0
  152. package/examples/E2E/jest.config.js +3 -0
  153. package/examples/E2E/metro.config.js +45 -0
  154. package/examples/E2E/package.json +65 -0
  155. package/examples/E2E/plugins/Logger.ts +16 -0
  156. package/examples/E2E/react-native.config.js +7 -0
  157. package/examples/E2E/workspace.js +5 -0
  158. package/examples/E2E/yarn.lock +10898 -0
  159. package/examples/E2E-73/.bundle/config +2 -0
  160. package/examples/E2E-73/.detoxrc.js +96 -0
  161. package/examples/E2E-73/.eslintrc.js +4 -0
  162. package/examples/E2E-73/.mise.toml +5 -0
  163. package/examples/E2E-73/.prettierrc.js +7 -0
  164. package/examples/E2E-73/.watchmanconfig +1 -0
  165. package/examples/E2E-73/App.tsx +175 -0
  166. package/examples/E2E-73/Gemfile +7 -0
  167. package/examples/E2E-73/Gemfile.lock +99 -0
  168. package/examples/E2E-73/Home.tsx +206 -0
  169. package/examples/E2E-73/Modal.tsx +25 -0
  170. package/examples/E2E-73/README.md +79 -0
  171. package/examples/E2E-73/SecondPage.tsx +25 -0
  172. package/examples/E2E-73/android/app/build.gradle +119 -0
  173. package/examples/E2E-73/android/app/debug.keystore +0 -0
  174. package/examples/E2E-73/android/app/proguard-rules.pro +10 -0
  175. package/examples/E2E-73/android/app/src/debug/AndroidManifest.xml +9 -0
  176. package/examples/E2E-73/android/app/src/main/AndroidManifest.xml +25 -0
  177. package/examples/E2E-73/android/app/src/main/java/com/analyticsreactnativee2e73/MainActivity.kt +22 -0
  178. package/examples/E2E-73/android/app/src/main/java/com/analyticsreactnativee2e73/MainApplication.kt +45 -0
  179. package/examples/E2E-73/android/app/src/main/res/drawable/rn_edit_text_material.xml +36 -0
  180. package/examples/E2E-73/android/app/src/main/res/mipmap-hdpi/ic_launcher.png +0 -0
  181. package/examples/E2E-73/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png +0 -0
  182. package/examples/E2E-73/android/app/src/main/res/mipmap-mdpi/ic_launcher.png +0 -0
  183. package/examples/E2E-73/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png +0 -0
  184. package/examples/E2E-73/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png +0 -0
  185. package/examples/E2E-73/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png +0 -0
  186. package/examples/E2E-73/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png +0 -0
  187. package/examples/E2E-73/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png +0 -0
  188. package/examples/E2E-73/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png +0 -0
  189. package/examples/E2E-73/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png +0 -0
  190. package/examples/E2E-73/android/app/src/main/res/values/strings.xml +3 -0
  191. package/examples/E2E-73/android/app/src/main/res/values/styles.xml +9 -0
  192. package/examples/E2E-73/android/build.gradle +21 -0
  193. package/examples/E2E-73/android/gradle/wrapper/gradle-wrapper.jar +0 -0
  194. package/examples/E2E-73/android/gradle/wrapper/gradle-wrapper.properties +7 -0
  195. package/examples/E2E-73/android/gradle.properties +41 -0
  196. package/examples/E2E-73/android/gradlew +249 -0
  197. package/examples/E2E-73/android/gradlew.bat +92 -0
  198. package/examples/E2E-73/android/settings.gradle +4 -0
  199. package/examples/E2E-73/app.json +4 -0
  200. package/examples/E2E-73/babel.config.js +14 -0
  201. package/examples/E2E-73/e2e/jest.config.js +13 -0
  202. package/examples/E2E-73/e2e/main.e2e.js +192 -0
  203. package/examples/E2E-73/e2e/matchers.js +34 -0
  204. package/examples/E2E-73/e2e/mockServer.js +56 -0
  205. package/examples/E2E-73/index.js +9 -0
  206. package/examples/E2E-73/ios/.xcode.env +11 -0
  207. package/examples/E2E-73/ios/AnalyticsReactNativeE2E73/AppDelegate.h +6 -0
  208. package/examples/E2E-73/ios/AnalyticsReactNativeE2E73/AppDelegate.mm +31 -0
  209. package/examples/E2E-73/ios/AnalyticsReactNativeE2E73/Images.xcassets/AppIcon.appiconset/Contents.json +53 -0
  210. package/examples/E2E-73/ios/AnalyticsReactNativeE2E73/Images.xcassets/Contents.json +6 -0
  211. package/examples/E2E-73/ios/AnalyticsReactNativeE2E73/Info.plist +51 -0
  212. package/examples/E2E-73/ios/AnalyticsReactNativeE2E73/LaunchScreen.storyboard +47 -0
  213. package/examples/E2E-73/ios/AnalyticsReactNativeE2E73/main.m +10 -0
  214. package/examples/E2E-73/ios/AnalyticsReactNativeE2E73.xcodeproj/project.pbxproj +700 -0
  215. package/examples/E2E-73/ios/AnalyticsReactNativeE2E73.xcodeproj/xcshareddata/xcschemes/AnalyticsReactNativeE2E73.xcscheme +88 -0
  216. package/examples/E2E-73/ios/AnalyticsReactNativeE2E73.xcworkspace/contents.xcworkspacedata +10 -0
  217. package/examples/E2E-73/ios/AnalyticsReactNativeE2E73Tests/AnalyticsReactNativeE2E73Tests.m +66 -0
  218. package/examples/E2E-73/ios/AnalyticsReactNativeE2E73Tests/Info.plist +24 -0
  219. package/examples/E2E-73/ios/Podfile +55 -0
  220. package/examples/E2E-73/ios/Podfile.lock +1425 -0
  221. package/examples/E2E-73/jest.config.js +3 -0
  222. package/examples/E2E-73/metro.config.js +45 -0
  223. package/examples/E2E-73/package.json +62 -0
  224. package/examples/E2E-73/plugins/Logger.ts +16 -0
  225. package/examples/E2E-73/react-native.config.js +12 -0
  226. package/examples/E2E-73/tsconfig.json +3 -0
  227. package/examples/E2E-73/workspace.js +5 -0
  228. package/examples/E2E-73/yarn.lock +10789 -0
  229. package/examples/README.md +142 -0
  230. package/examples/linkHelper.js +45 -0
  231. package/jest.config.js +7 -0
  232. package/multi-release.config.js +7 -0
  233. package/package.json +79 -0
  234. package/packages/core/CHANGELOG.md +274 -0
  235. package/packages/core/LICENSE +21 -0
  236. package/packages/core/README.md +3 -0
  237. package/packages/core/android/build.gradle +96 -0
  238. package/packages/core/android/gradle.properties +5 -0
  239. package/packages/core/android/src/main/AndroidManifest.xml +4 -0
  240. package/packages/core/android/src/main/AndroidManifestNew.xml +3 -0
  241. package/packages/core/android/src/main/java/com/segmentanalyticsreactnative/AnalyticsReactNativeModule.kt +265 -0
  242. package/packages/core/android/src/main/java/com/segmentanalyticsreactnative/AnalyticsReactNativePackage.kt +43 -0
  243. package/packages/core/babel.config.js +3 -0
  244. package/packages/core/constants-generator.js +17 -0
  245. package/packages/core/ios/AnalyticsReactNative-Bridging-Header.h +1 -0
  246. package/packages/core/ios/AnalyticsReactNative.m +7 -0
  247. package/packages/core/ios/AnalyticsReactNative.swift +142 -0
  248. package/packages/core/ios/AnalyticsReactNative.xcodeproj/project.pbxproj +281 -0
  249. package/packages/core/ios/PrivacyInfo.xcprivacy +70 -0
  250. package/packages/core/jest.config.js +5 -0
  251. package/packages/core/package.json +85 -0
  252. package/packages/core/release.config.js +3 -0
  253. package/packages/core/segment-analytics-react-native.podspec +35 -0
  254. package/packages/core/src/__tests__/__snapshots__/mapTransform.test.ts.snap +20 -0
  255. package/packages/core/src/__tests__/analytics.test.ts +252 -0
  256. package/packages/core/src/__tests__/api.test.ts +91 -0
  257. package/packages/core/src/__tests__/client.test.ts +27 -0
  258. package/packages/core/src/__tests__/context.test.ts +122 -0
  259. package/packages/core/src/__tests__/events.test.ts +234 -0
  260. package/packages/core/src/__tests__/internal/checkInstalledVersion.test.ts +221 -0
  261. package/packages/core/src/__tests__/internal/fetchSettings.test.ts +438 -0
  262. package/packages/core/src/__tests__/internal/handleAppStateChange.test.ts +178 -0
  263. package/packages/core/src/__tests__/internal/trackDeepLinks.test.ts +121 -0
  264. package/packages/core/src/__tests__/logger.test.ts +83 -0
  265. package/packages/core/src/__tests__/mapTransform.test.ts +63 -0
  266. package/packages/core/src/__tests__/methods/alias.test.ts +89 -0
  267. package/packages/core/src/__tests__/methods/flush.test.ts +120 -0
  268. package/packages/core/src/__tests__/methods/group.test.ts +48 -0
  269. package/packages/core/src/__tests__/methods/identify.test.ts +132 -0
  270. package/packages/core/src/__tests__/methods/process.test.ts +162 -0
  271. package/packages/core/src/__tests__/methods/screen.test.ts +48 -0
  272. package/packages/core/src/__tests__/methods/track.test.ts +49 -0
  273. package/packages/core/src/__tests__/timeline.test.ts +130 -0
  274. package/packages/core/src/__tests__/util.test.ts +200 -0
  275. package/packages/core/src/analytics.ts +1030 -0
  276. package/packages/core/src/api.ts +23 -0
  277. package/packages/core/src/client.tsx +76 -0
  278. package/packages/core/src/constants.ts +18 -0
  279. package/packages/core/src/context.ts +107 -0
  280. package/packages/core/src/errors.ts +123 -0
  281. package/packages/core/src/events.ts +75 -0
  282. package/packages/core/src/flushPolicies/__tests__/background-flush-policy.test.ts +39 -0
  283. package/packages/core/src/flushPolicies/__tests__/count-flush-policy.test.ts +28 -0
  284. package/packages/core/src/flushPolicies/__tests__/flush-policy-executer.test.ts +85 -0
  285. package/packages/core/src/flushPolicies/__tests__/timer-flush-policy.test.ts +30 -0
  286. package/packages/core/src/flushPolicies/background-flush-policy.ts +21 -0
  287. package/packages/core/src/flushPolicies/count-flush-policy.ts +31 -0
  288. package/packages/core/src/flushPolicies/flush-policy-executer.ts +100 -0
  289. package/packages/core/src/flushPolicies/index.ts +5 -0
  290. package/packages/core/src/flushPolicies/startup-flush-policy.ts +20 -0
  291. package/packages/core/src/flushPolicies/timer-flush-policy.ts +45 -0
  292. package/packages/core/src/flushPolicies/types.ts +93 -0
  293. package/packages/core/src/index.ts +28 -0
  294. package/packages/core/src/logger.ts +37 -0
  295. package/packages/core/src/mapTransform.ts +48 -0
  296. package/packages/core/src/plugin.ts +212 -0
  297. package/packages/core/src/plugins/ConsentPlugin.ts +200 -0
  298. package/packages/core/src/plugins/DestinationMetadataEnrichment.ts +67 -0
  299. package/packages/core/src/plugins/QueueFlushingPlugin.ts +149 -0
  300. package/packages/core/src/plugins/SegmentDestination.ts +153 -0
  301. package/packages/core/src/plugins/__tests__/QueueFlushingPlugin.test.ts +143 -0
  302. package/packages/core/src/plugins/__tests__/SegmentDestination.test.ts +549 -0
  303. package/packages/core/src/plugins/__tests__/consent/consentNotEnabledAtSegment.test.ts +123 -0
  304. package/packages/core/src/plugins/__tests__/consent/destinationMultipleCategories.test.ts +147 -0
  305. package/packages/core/src/plugins/__tests__/consent/idfa.test.ts +101 -0
  306. package/packages/core/src/plugins/__tests__/consent/mockSettings/ConsentNotEnabledAtSegment.json +70 -0
  307. package/packages/core/src/plugins/__tests__/consent/mockSettings/DestinationsMultipleCategories.json +73 -0
  308. package/packages/core/src/plugins/__tests__/consent/mockSettings/NoUnmappedDestinations.json +105 -0
  309. package/packages/core/src/plugins/__tests__/consent/mockSettings/UnmappedDestinations.json +101 -0
  310. package/packages/core/src/plugins/__tests__/consent/noUnmapped.test.ts +234 -0
  311. package/packages/core/src/plugins/__tests__/consent/unmapped.test.ts +265 -0
  312. package/packages/core/src/plugins/__tests__/consent/utils.ts +75 -0
  313. package/packages/core/src/storage/__tests__/sovranStorage.test.ts +153 -0
  314. package/packages/core/src/storage/helpers.ts +25 -0
  315. package/packages/core/src/storage/index.ts +3 -0
  316. package/packages/core/src/storage/sovranStorage.ts +558 -0
  317. package/packages/core/src/storage/types.ts +106 -0
  318. package/packages/core/src/test-helpers/index.ts +7 -0
  319. package/packages/core/src/test-helpers/mockDestinationPlugin.ts +7 -0
  320. package/packages/core/src/test-helpers/mockEventStore.ts +35 -0
  321. package/packages/core/src/test-helpers/mockLogger.ts +10 -0
  322. package/packages/core/src/test-helpers/mockSegmentStore.ts +266 -0
  323. package/packages/core/src/test-helpers/mockTimeline.ts +9 -0
  324. package/packages/core/src/test-helpers/setupSegmentClient.ts +59 -0
  325. package/packages/core/src/test-helpers/utils.ts +23 -0
  326. package/packages/core/src/timeline.ts +136 -0
  327. package/packages/core/src/types.ts +392 -0
  328. package/packages/core/src/util.ts +288 -0
  329. package/packages/core/src/uuid.ts +7 -0
  330. package/packages/core/tsconfig.json +10 -0
  331. package/packages/core/tsconfig.linter.json +11 -0
  332. package/packages/plugins/plugin-adjust/CHANGELOG.md +60 -0
  333. package/packages/plugins/plugin-adjust/LICENSE +21 -0
  334. package/packages/plugins/plugin-adjust/README.md +72 -0
  335. package/packages/plugins/plugin-adjust/babel.config.js +3 -0
  336. package/packages/plugins/plugin-adjust/jest.config.js +5 -0
  337. package/packages/plugins/plugin-adjust/package.json +72 -0
  338. package/packages/plugins/plugin-adjust/release.config.js +3 -0
  339. package/packages/plugins/plugin-adjust/src/AdjustPlugin.tsx +92 -0
  340. package/packages/plugins/plugin-adjust/src/index.ts +1 -0
  341. package/packages/plugins/plugin-adjust/src/methods/__mocks__/react-native-adjust.ts +19 -0
  342. package/packages/plugins/plugin-adjust/src/methods/__tests__/identify.test.ts +34 -0
  343. package/packages/plugins/plugin-adjust/src/methods/__tests__/reset.test.ts +15 -0
  344. package/packages/plugins/plugin-adjust/src/methods/__tests__/track.test.ts +148 -0
  345. package/packages/plugins/plugin-adjust/src/methods/identify.ts +14 -0
  346. package/packages/plugins/plugin-adjust/src/methods/reset.ts +9 -0
  347. package/packages/plugins/plugin-adjust/src/methods/track.ts +47 -0
  348. package/packages/plugins/plugin-adjust/src/util.ts +29 -0
  349. package/packages/plugins/plugin-adjust/tsconfig.json +10 -0
  350. package/packages/plugins/plugin-advertising-id/CHANGELOG.md +101 -0
  351. package/packages/plugins/plugin-advertising-id/CONTRIBUTING.md +196 -0
  352. package/packages/plugins/plugin-advertising-id/LICENSE +21 -0
  353. package/packages/plugins/plugin-advertising-id/README.md +40 -0
  354. package/packages/plugins/plugin-advertising-id/android/build.gradle +96 -0
  355. package/packages/plugins/plugin-advertising-id/android/gradle.properties +5 -0
  356. package/packages/plugins/plugin-advertising-id/android/src/main/AndroidManifest.xml +4 -0
  357. package/packages/plugins/plugin-advertising-id/android/src/main/AndroidManifestNew.xml +3 -0
  358. package/packages/plugins/plugin-advertising-id/android/src/main/java/com/reactnativeanalyticsreactnativepluginadvertisingid/AnalyticsReactNativePluginAdvertisingIdModule.kt +64 -0
  359. package/packages/plugins/plugin-advertising-id/android/src/main/java/com/reactnativeanalyticsreactnativepluginadvertisingid/AnalyticsReactNativePluginAdvertisingIdPackage.kt +17 -0
  360. package/packages/plugins/plugin-advertising-id/babel.config.js +3 -0
  361. package/packages/plugins/plugin-advertising-id/jest.config.js +5 -0
  362. package/packages/plugins/plugin-advertising-id/package.json +70 -0
  363. package/packages/plugins/plugin-advertising-id/release.config.js +3 -0
  364. package/packages/plugins/plugin-advertising-id/src/AdvertisingIdPlugin.ts +172 -0
  365. package/packages/plugins/plugin-advertising-id/src/index.ts +1 -0
  366. package/packages/plugins/plugin-advertising-id/src/types.ts +3 -0
  367. package/packages/plugins/plugin-advertising-id/tsconfig.json +10 -0
  368. package/packages/plugins/plugin-amplitudeSession/CHANGELOG.md +46 -0
  369. package/packages/plugins/plugin-amplitudeSession/LICENSE +21 -0
  370. package/packages/plugins/plugin-amplitudeSession/README.md +66 -0
  371. package/packages/plugins/plugin-amplitudeSession/babel.config.js +3 -0
  372. package/packages/plugins/plugin-amplitudeSession/jest.config.js +5 -0
  373. package/packages/plugins/plugin-amplitudeSession/package.json +71 -0
  374. package/packages/plugins/plugin-amplitudeSession/release.config.js +3 -0
  375. package/packages/plugins/plugin-amplitudeSession/src/AmplitudeSessionPlugin.tsx +327 -0
  376. package/packages/plugins/plugin-amplitudeSession/src/__tests__/AmplitudeSessionPlugin.test.ts +769 -0
  377. package/packages/plugins/plugin-amplitudeSession/src/index.ts +1 -0
  378. package/packages/plugins/plugin-amplitudeSession/tsconfig.json +10 -0
  379. package/packages/plugins/plugin-appsflyer/CHANGELOG.md +64 -0
  380. package/packages/plugins/plugin-appsflyer/LICENSE +21 -0
  381. package/packages/plugins/plugin-appsflyer/README.md +90 -0
  382. package/packages/plugins/plugin-appsflyer/babel.config.js +3 -0
  383. package/packages/plugins/plugin-appsflyer/jest.config.js +5 -0
  384. package/packages/plugins/plugin-appsflyer/package.json +74 -0
  385. package/packages/plugins/plugin-appsflyer/release.config.js +3 -0
  386. package/packages/plugins/plugin-appsflyer/src/AppsflyerPlugin.tsx +218 -0
  387. package/packages/plugins/plugin-appsflyer/src/__tests__/AppsflyerPlugin.test.ts +20 -0
  388. package/packages/plugins/plugin-appsflyer/src/index.ts +1 -0
  389. package/packages/plugins/plugin-appsflyer/src/methods/__mocks__/react-native-appsflyer.ts +11 -0
  390. package/packages/plugins/plugin-appsflyer/src/methods/__tests__/identify.test.ts +57 -0
  391. package/packages/plugins/plugin-appsflyer/src/methods/__tests__/track.test.ts +99 -0
  392. package/packages/plugins/plugin-appsflyer/src/methods/identify.ts +42 -0
  393. package/packages/plugins/plugin-appsflyer/src/methods/track.ts +61 -0
  394. package/packages/plugins/plugin-appsflyer/src/types.ts +9 -0
  395. package/packages/plugins/plugin-appsflyer/tsconfig.json +10 -0
  396. package/packages/plugins/plugin-branch/CHANGELOG.md +51 -0
  397. package/packages/plugins/plugin-branch/LICENSE +21 -0
  398. package/packages/plugins/plugin-branch/README.md +71 -0
  399. package/packages/plugins/plugin-branch/babel.config.js +3 -0
  400. package/packages/plugins/plugin-branch/jest.config.js +5 -0
  401. package/packages/plugins/plugin-branch/package.json +74 -0
  402. package/packages/plugins/plugin-branch/release.config.js +3 -0
  403. package/packages/plugins/plugin-branch/src/BranchPlugin.ts +42 -0
  404. package/packages/plugins/plugin-branch/src/index.ts +1 -0
  405. package/packages/plugins/plugin-branch/src/methods/__mocks__/react-native-branch.ts +16 -0
  406. package/packages/plugins/plugin-branch/src/methods/__tests__/alias.test.ts +23 -0
  407. package/packages/plugins/plugin-branch/src/methods/__tests__/identify.test.ts +23 -0
  408. package/packages/plugins/plugin-branch/src/methods/__tests__/screen.test.ts +38 -0
  409. package/packages/plugins/plugin-branch/src/methods/__tests__/track.test.ts +73 -0
  410. package/packages/plugins/plugin-branch/src/methods/alias.ts +9 -0
  411. package/packages/plugins/plugin-branch/src/methods/identify.ts +9 -0
  412. package/packages/plugins/plugin-branch/src/methods/parameterMapping.ts +109 -0
  413. package/packages/plugins/plugin-branch/src/methods/reset.ts +5 -0
  414. package/packages/plugins/plugin-branch/src/methods/screen.ts +17 -0
  415. package/packages/plugins/plugin-branch/src/methods/track.ts +18 -0
  416. package/packages/plugins/plugin-branch/src/methods/util.ts +64 -0
  417. package/packages/plugins/plugin-branch/tsconfig.json +10 -0
  418. package/packages/plugins/plugin-braze/CHANGELOG.md +101 -0
  419. package/packages/plugins/plugin-braze/LICENSE +21 -0
  420. package/packages/plugins/plugin-braze/README.md +72 -0
  421. package/packages/plugins/plugin-braze/babel.config.js +3 -0
  422. package/packages/plugins/plugin-braze/jest.config.js +5 -0
  423. package/packages/plugins/plugin-braze/package.json +74 -0
  424. package/packages/plugins/plugin-braze/release.config.js +3 -0
  425. package/packages/plugins/plugin-braze/src/BrazePlugin.tsx +346 -0
  426. package/packages/plugins/plugin-braze/src/index.ts +1 -0
  427. package/packages/plugins/plugin-braze/src/methods/__mocks__/@braze/react-native-sdk.ts +31 -0
  428. package/packages/plugins/plugin-braze/src/methods/__tests__/flush.test.ts +15 -0
  429. package/packages/plugins/plugin-braze/src/methods/__tests__/identify.test.ts +114 -0
  430. package/packages/plugins/plugin-braze/src/methods/__tests__/track.test.ts +321 -0
  431. package/packages/plugins/plugin-braze/src/methods/flush.ts +5 -0
  432. package/packages/plugins/plugin-braze/tsconfig.json +10 -0
  433. package/packages/plugins/plugin-braze-middleware/CHANGELOG.md +32 -0
  434. package/packages/plugins/plugin-braze-middleware/LICENSE +21 -0
  435. package/packages/plugins/plugin-braze-middleware/README.md +67 -0
  436. package/packages/plugins/plugin-braze-middleware/babel.config.js +3 -0
  437. package/packages/plugins/plugin-braze-middleware/jest.config.js +5 -0
  438. package/packages/plugins/plugin-braze-middleware/package.json +72 -0
  439. package/packages/plugins/plugin-braze-middleware/release.config.js +3 -0
  440. package/packages/plugins/plugin-braze-middleware/src/BrazeMiddlewarePlugin.tsx +38 -0
  441. package/packages/plugins/plugin-braze-middleware/src/index.ts +1 -0
  442. package/packages/plugins/plugin-braze-middleware/tsconfig.json +10 -0
  443. package/packages/plugins/plugin-clevertap/CHANGELOG.md +32 -0
  444. package/packages/plugins/plugin-clevertap/LICENSE +21 -0
  445. package/packages/plugins/plugin-clevertap/README.md +71 -0
  446. package/packages/plugins/plugin-clevertap/babel.config.js +3 -0
  447. package/packages/plugins/plugin-clevertap/jest.config.js +5 -0
  448. package/packages/plugins/plugin-clevertap/package.json +72 -0
  449. package/packages/plugins/plugin-clevertap/release.config.js +3 -0
  450. package/packages/plugins/plugin-clevertap/src/ClevertapPlugin.ts +75 -0
  451. package/packages/plugins/plugin-clevertap/src/__mocks__/clevertap-react-native.ts +5 -0
  452. package/packages/plugins/plugin-clevertap/src/__tests__/ClevertapPlugin.test.ts +164 -0
  453. package/packages/plugins/plugin-clevertap/src/index.ts +1 -0
  454. package/packages/plugins/plugin-clevertap/src/parameterMapping.ts +19 -0
  455. package/packages/plugins/plugin-clevertap/tsconfig.json +10 -0
  456. package/packages/plugins/plugin-destination-filters/CHANGELOG.md +39 -0
  457. package/packages/plugins/plugin-destination-filters/LICENSE +21 -0
  458. package/packages/plugins/plugin-destination-filters/README.md +71 -0
  459. package/packages/plugins/plugin-destination-filters/babel.config.js +3 -0
  460. package/packages/plugins/plugin-destination-filters/jest.config.js +5 -0
  461. package/packages/plugins/plugin-destination-filters/package.json +77 -0
  462. package/packages/plugins/plugin-destination-filters/release.config.js +3 -0
  463. package/packages/plugins/plugin-destination-filters/src/DestinationFilters.ts +90 -0
  464. package/packages/plugins/plugin-destination-filters/src/__tests__/DestinationFilters.test.ts +102 -0
  465. package/packages/plugins/plugin-destination-filters/src/index.tsx +1 -0
  466. package/packages/plugins/plugin-destination-filters/tsconfig.json +10 -0
  467. package/packages/plugins/plugin-device-token/CHANGELOG.md +71 -0
  468. package/packages/plugins/plugin-device-token/LICENSE +21 -0
  469. package/packages/plugins/plugin-device-token/README.md +98 -0
  470. package/packages/plugins/plugin-device-token/babel.config.js +3 -0
  471. package/packages/plugins/plugin-device-token/jest.config.js +5 -0
  472. package/packages/plugins/plugin-device-token/package.json +76 -0
  473. package/packages/plugins/plugin-device-token/release.config.js +3 -0
  474. package/packages/plugins/plugin-device-token/src/DeviceTokenPlugin.tsx +94 -0
  475. package/packages/plugins/plugin-device-token/src/index.ts +1 -0
  476. package/packages/plugins/plugin-device-token/src/methods/___tests__/DeviceTokenPlugin.test.ts +94 -0
  477. package/packages/plugins/plugin-device-token/tsconfig.json +10 -0
  478. package/packages/plugins/plugin-facebook-app-events/CHANGELOG.md +78 -0
  479. package/packages/plugins/plugin-facebook-app-events/LICENSE +21 -0
  480. package/packages/plugins/plugin-facebook-app-events/README.md +73 -0
  481. package/packages/plugins/plugin-facebook-app-events/babel.config.js +3 -0
  482. package/packages/plugins/plugin-facebook-app-events/jest.config.js +5 -0
  483. package/packages/plugins/plugin-facebook-app-events/package.json +72 -0
  484. package/packages/plugins/plugin-facebook-app-events/release.config.js +3 -0
  485. package/packages/plugins/plugin-facebook-app-events/src/FacebookAppEventsPlugin.ts +192 -0
  486. package/packages/plugins/plugin-facebook-app-events/src/__tests__/FacebookAppEventsPlugin.test.ts +284 -0
  487. package/packages/plugins/plugin-facebook-app-events/src/index.ts +1 -0
  488. package/packages/plugins/plugin-facebook-app-events/src/methods/__tests__/screen.test.ts +33 -0
  489. package/packages/plugins/plugin-facebook-app-events/src/methods/screen.ts +35 -0
  490. package/packages/plugins/plugin-facebook-app-events/src/parameterMapping.ts +46 -0
  491. package/packages/plugins/plugin-facebook-app-events/src/utils.ts +12 -0
  492. package/packages/plugins/plugin-facebook-app-events/tsconfig.json +10 -0
  493. package/packages/plugins/plugin-firebase/CHANGELOG.md +102 -0
  494. package/packages/plugins/plugin-firebase/LICENSE +21 -0
  495. package/packages/plugins/plugin-firebase/README.md +72 -0
  496. package/packages/plugins/plugin-firebase/babel.config.js +3 -0
  497. package/packages/plugins/plugin-firebase/jest.config.js +5 -0
  498. package/packages/plugins/plugin-firebase/package.json +74 -0
  499. package/packages/plugins/plugin-firebase/release.config.js +3 -0
  500. package/packages/plugins/plugin-firebase/src/FirebasePlugin.tsx +96 -0
  501. package/packages/plugins/plugin-firebase/src/index.ts +1 -0
  502. package/packages/plugins/plugin-firebase/src/methods/___tests__/identify.test.ts +73 -0
  503. package/packages/plugins/plugin-firebase/src/methods/___tests__/reset.test.ts +20 -0
  504. package/packages/plugins/plugin-firebase/src/methods/___tests__/screen.test.ts +33 -0
  505. package/packages/plugins/plugin-firebase/src/methods/___tests__/track.test.ts +85 -0
  506. package/packages/plugins/plugin-firebase/src/methods/parameterMapping.ts +45 -0
  507. package/packages/plugins/plugin-firebase/src/methods/reset.ts +5 -0
  508. package/packages/plugins/plugin-firebase/src/methods/screen.ts +12 -0
  509. package/packages/plugins/plugin-firebase/src/methods/track.ts +26 -0
  510. package/packages/plugins/plugin-firebase/tsconfig.json +10 -0
  511. package/packages/plugins/plugin-idfa/CHANGELOG.md +62 -0
  512. package/packages/plugins/plugin-idfa/LICENSE +21 -0
  513. package/packages/plugins/plugin-idfa/README.md +105 -0
  514. package/packages/plugins/plugin-idfa/babel.config.js +3 -0
  515. package/packages/plugins/plugin-idfa/ios/AnalyticsReactNativePluginIdfa-Bridging-Header.h +2 -0
  516. package/packages/plugins/plugin-idfa/ios/AnalyticsReactNativePluginIdfa.m +11 -0
  517. package/packages/plugins/plugin-idfa/ios/AnalyticsReactNativePluginIdfa.swift +68 -0
  518. package/packages/plugins/plugin-idfa/ios/AnalyticsReactNativePluginIdfa.xcodeproj/project.pbxproj +293 -0
  519. package/packages/plugins/plugin-idfa/jest.config.js +5 -0
  520. package/packages/plugins/plugin-idfa/package.json +70 -0
  521. package/packages/plugins/plugin-idfa/release.config.js +3 -0
  522. package/packages/plugins/plugin-idfa/segment-analytics-react-native-plugin-idfa.podspec +19 -0
  523. package/packages/plugins/plugin-idfa/src/AnalyticsReactNativePluginIdfa.e2e.mock.ts +12 -0
  524. package/packages/plugins/plugin-idfa/src/AnalyticsReactNativePluginIdfa.ts +18 -0
  525. package/packages/plugins/plugin-idfa/src/IdfaPlugin.tsx +80 -0
  526. package/packages/plugins/plugin-idfa/src/index.ts +1 -0
  527. package/packages/plugins/plugin-idfa/src/types.ts +13 -0
  528. package/packages/plugins/plugin-idfa/tsconfig.json +10 -0
  529. package/packages/plugins/plugin-mixpanel/CHANGELOG.md +73 -0
  530. package/packages/plugins/plugin-mixpanel/LICENSE +21 -0
  531. package/packages/plugins/plugin-mixpanel/README.md +71 -0
  532. package/packages/plugins/plugin-mixpanel/babel.config.js +3 -0
  533. package/packages/plugins/plugin-mixpanel/jest.config.js +5 -0
  534. package/packages/plugins/plugin-mixpanel/package.json +72 -0
  535. package/packages/plugins/plugin-mixpanel/release.config.js +3 -0
  536. package/packages/plugins/plugin-mixpanel/src/MixpanelPlugin.ts +106 -0
  537. package/packages/plugins/plugin-mixpanel/src/index.ts +1 -0
  538. package/packages/plugins/plugin-mixpanel/src/methods/__mocks__/mixpanel-react-native.ts +67 -0
  539. package/packages/plugins/plugin-mixpanel/src/methods/__tests__/MixpanelPlugin.test.ts +57 -0
  540. package/packages/plugins/plugin-mixpanel/src/methods/__tests__/__helpers__/constants.ts +18 -0
  541. package/packages/plugins/plugin-mixpanel/src/methods/__tests__/alias.test.ts +47 -0
  542. package/packages/plugins/plugin-mixpanel/src/methods/__tests__/group.test.ts +49 -0
  543. package/packages/plugins/plugin-mixpanel/src/methods/__tests__/identify.test.ts +103 -0
  544. package/packages/plugins/plugin-mixpanel/src/methods/__tests__/screen.test.ts +119 -0
  545. package/packages/plugins/plugin-mixpanel/src/methods/__tests__/track.test.ts +110 -0
  546. package/packages/plugins/plugin-mixpanel/src/methods/alias.ts +28 -0
  547. package/packages/plugins/plugin-mixpanel/src/methods/group.ts +26 -0
  548. package/packages/plugins/plugin-mixpanel/src/methods/identify.ts +72 -0
  549. package/packages/plugins/plugin-mixpanel/src/methods/screen.ts +43 -0
  550. package/packages/plugins/plugin-mixpanel/src/methods/track.ts +60 -0
  551. package/packages/plugins/plugin-mixpanel/src/types.ts +15 -0
  552. package/packages/plugins/plugin-mixpanel/tsconfig.json +10 -0
  553. package/packages/plugins/plugin-onetrust/CHANGELOG.md +16 -0
  554. package/packages/plugins/plugin-onetrust/LICENSE +21 -0
  555. package/packages/plugins/plugin-onetrust/README.md +155 -0
  556. package/packages/plugins/plugin-onetrust/babel.config.js +3 -0
  557. package/packages/plugins/plugin-onetrust/jest.config.js +6 -0
  558. package/packages/plugins/plugin-onetrust/package.json +75 -0
  559. package/packages/plugins/plugin-onetrust/release.config.js +3 -0
  560. package/packages/plugins/plugin-onetrust/src/OneTrustProvider.ts +71 -0
  561. package/packages/plugins/plugin-onetrust/src/index.tsx +1 -0
  562. package/packages/plugins/plugin-onetrust/tsconfig.json +10 -0
  563. package/packages/shared/__mocks__/context.ts +35 -0
  564. package/packages/shared/__mocks__/react-native-get-random-values.ts +1 -0
  565. package/packages/shared/__mocks__/react-native.ts +53 -0
  566. package/packages/shared/__mocks__/uuid.ts +3 -0
  567. package/packages/shared/jest.config.base.js +38 -0
  568. package/packages/shared/package.json +19 -0
  569. package/packages/shared/src/setup.ts +7 -0
  570. package/packages/shared/tsconfig.json +15 -0
  571. package/packages/sovran/CHANGELOG.md +42 -0
  572. package/packages/sovran/CONTRIBUTING.md +196 -0
  573. package/packages/sovran/LICENSE +21 -0
  574. package/packages/sovran/README.md +174 -0
  575. package/packages/sovran/android/build.gradle +94 -0
  576. package/packages/sovran/android/gradle.properties +5 -0
  577. package/packages/sovran/android/src/main/AndroidManifest.xml +4 -0
  578. package/packages/sovran/android/src/main/AndroidManifestNew.xml +3 -0
  579. package/packages/sovran/android/src/main/java/com/reactnativesovran/Sovran.kt +45 -0
  580. package/packages/sovran/android/src/main/java/com/reactnativesovran/SovranModule.kt +55 -0
  581. package/packages/sovran/babel.config.js +3 -0
  582. package/packages/sovran/ios/Sovran-Bridging-Header.h +3 -0
  583. package/packages/sovran/ios/Sovran.m +8 -0
  584. package/packages/sovran/ios/Sovran.swift +67 -0
  585. package/packages/sovran/ios/Sovran.xcodeproj/project.pbxproj +279 -0
  586. package/packages/sovran/jest.config.js +5 -0
  587. package/packages/sovran/package.json +89 -0
  588. package/packages/sovran/release.config.js +3 -0
  589. package/packages/sovran/sovran-react-native.podspec +33 -0
  590. package/packages/sovran/src/__tests__/bridge.test.ts +39 -0
  591. package/packages/sovran/src/__tests__/index.test.tsx +1 -0
  592. package/packages/sovran/src/__tests__/store.test.ts +397 -0
  593. package/packages/sovran/src/bridge.ts +48 -0
  594. package/packages/sovran/src/index.tsx +52 -0
  595. package/packages/sovran/src/persistor/async-storage-persistor.ts +63 -0
  596. package/packages/sovran/src/persistor/index.ts +2 -0
  597. package/packages/sovran/src/persistor/persistor.ts +31 -0
  598. package/packages/sovran/src/store.ts +232 -0
  599. package/packages/sovran/tsconfig.json +9 -0
  600. package/release.config.js +13 -0
  601. package/tsconfig.json +44 -0
  602. package/tsconfig.linter.json +36 -0
@@ -0,0 +1,769 @@
1
+ /* eslint-disable @typescript-eslint/no-unsafe-assignment */
2
+ /* eslint-disable @typescript-eslint/no-explicit-any */
3
+ import { AmplitudeSessionPlugin } from '../AmplitudeSessionPlugin';
4
+ // Import the constant for consistent timeout values
5
+ const MAX_SESSION_TIME_IN_MS = 300000;
6
+ import AsyncStorage from '@react-native-async-storage/async-storage';
7
+ import {
8
+ EventType,
9
+ TrackEventType,
10
+ IdentifyEventType,
11
+ ScreenEventType,
12
+ SegmentAPISettings,
13
+ UpdateType,
14
+ } from '@segment/analytics-react-native';
15
+ import { AppState } from 'react-native';
16
+
17
+ // AppState will be mocked by the base setup, we'll spy on it in the tests
18
+
19
+ describe('AmplitudeSessionPlugin', () => {
20
+ let plugin: AmplitudeSessionPlugin;
21
+ let mockAsyncStorage: jest.Mocked<typeof AsyncStorage>;
22
+
23
+ beforeEach(() => {
24
+ jest.clearAllMocks();
25
+ jest.useFakeTimers();
26
+
27
+ plugin = new AmplitudeSessionPlugin();
28
+
29
+ mockAsyncStorage = AsyncStorage as jest.Mocked<typeof AsyncStorage>;
30
+ mockAsyncStorage.getItem.mockResolvedValue(null);
31
+ mockAsyncStorage.setItem.mockResolvedValue();
32
+ mockAsyncStorage.removeItem.mockResolvedValue();
33
+ });
34
+
35
+ afterEach(() => {
36
+ jest.useRealTimers();
37
+ });
38
+
39
+ const setupPluginWithClient = async () => {
40
+ const mockClient = {
41
+ track: jest.fn(),
42
+ } as any;
43
+
44
+ await plugin.configure(mockClient);
45
+ plugin.update(
46
+ { integrations: { 'Actions Amplitude': {} } } as SegmentAPISettings,
47
+ UpdateType.initial
48
+ );
49
+
50
+ return { client: mockClient };
51
+ };
52
+
53
+ describe('startNewSession scenarios', () => {
54
+ beforeEach(async () => {
55
+ await setupPluginWithClient();
56
+ });
57
+
58
+ it('should start a new session when sessionId is -1', async () => {
59
+ plugin.sessionId = -1;
60
+ plugin.lastEventTime = -1;
61
+ plugin.resetPending = false;
62
+
63
+ const mockEvent: TrackEventType = {
64
+ type: EventType.TrackEvent,
65
+ event: 'test_event',
66
+ properties: {},
67
+ messageId: 'msg-1',
68
+ timestamp: '2023-01-01T00:00:00.000Z',
69
+ anonymousId: 'anon-1',
70
+ };
71
+
72
+ await plugin.execute(mockEvent);
73
+
74
+ expect(plugin.sessionId).toBeGreaterThan(0);
75
+ expect(plugin.analytics?.track).toHaveBeenCalledWith('session_start', {
76
+ integrations: {
77
+ 'Actions Amplitude': { session_id: plugin.sessionId },
78
+ },
79
+ });
80
+ });
81
+
82
+ it('should start a new session when session has expired (>MAX_SESSION_TIME_IN_MS)', async () => {
83
+ const baseTime = Date.now();
84
+ jest.setSystemTime(baseTime);
85
+ plugin.active = true;
86
+ plugin.sessionId = baseTime - 1000;
87
+ plugin.lastEventTime = baseTime - (MAX_SESSION_TIME_IN_MS + 1000); // 61 seconds ago
88
+ plugin.resetPending = false;
89
+
90
+ const mockEvent: TrackEventType = {
91
+ type: EventType.TrackEvent,
92
+ event: 'test_event',
93
+ properties: {},
94
+ messageId: 'msg-1',
95
+ timestamp: '2023-01-01T00:00:00.000Z',
96
+ anonymousId: 'anon-1',
97
+ };
98
+
99
+ const oldSessionId = plugin.sessionId;
100
+ await plugin.execute(mockEvent);
101
+
102
+ expect(plugin.sessionId).not.toBe(oldSessionId);
103
+ expect(plugin.sessionId).toBeGreaterThan(oldSessionId);
104
+ expect(plugin.analytics?.track).toHaveBeenCalledWith('session_end', {
105
+ integrations: {
106
+ 'Actions Amplitude': { session_id: oldSessionId },
107
+ },
108
+ });
109
+ expect(plugin.analytics?.track).toHaveBeenCalledWith('session_start', {
110
+ integrations: {
111
+ 'Actions Amplitude': { session_id: plugin.sessionId },
112
+ },
113
+ });
114
+ });
115
+
116
+ it('should NOT start a new session when session is still active', async () => {
117
+ const baseTime = Date.now();
118
+ jest.setSystemTime(baseTime);
119
+
120
+ plugin.sessionId = baseTime - 1000;
121
+ plugin.lastEventTime = baseTime - 30000; // 30 seconds ago
122
+ plugin.resetPending = false;
123
+
124
+ const mockEvent: TrackEventType = {
125
+ type: EventType.TrackEvent,
126
+ event: 'test_event',
127
+ properties: {},
128
+ messageId: 'msg-1',
129
+ timestamp: '2023-01-01T00:00:00.000Z',
130
+ anonymousId: 'anon-1',
131
+ };
132
+
133
+ const oldSessionId = plugin.sessionId;
134
+ await plugin.execute(mockEvent);
135
+
136
+ expect(plugin.sessionId).toBe(oldSessionId);
137
+ expect(plugin.analytics?.track).not.toHaveBeenCalledWith(
138
+ 'session_start',
139
+ expect.any(Object)
140
+ );
141
+ });
142
+ });
143
+
144
+ describe('bug detection: multiple startNewSession calls', () => {
145
+ beforeEach(async () => {
146
+ await setupPluginWithClient();
147
+ });
148
+
149
+ it('BUG: should detect multiple session starts for rapid events (currently masked by 1000ms guard)', async () => {
150
+ const baseTime = Date.now();
151
+ jest.setSystemTime(baseTime);
152
+
153
+ plugin.sessionId = -1;
154
+ plugin.lastEventTime = -1;
155
+ plugin.resetPending = false;
156
+
157
+ const mockEvent: TrackEventType = {
158
+ type: EventType.TrackEvent,
159
+ event: 'test_event',
160
+ properties: {},
161
+ messageId: 'msg-1',
162
+ timestamp: '2023-01-01T00:00:00.000Z',
163
+ anonymousId: 'anon-1',
164
+ };
165
+
166
+ // First call should start session
167
+ await plugin.execute(mockEvent);
168
+ const firstSessionId = plugin.sessionId;
169
+
170
+ expect(plugin.analytics?.track).toHaveBeenCalledWith('session_start', {
171
+ integrations: {
172
+ 'Actions Amplitude': { session_id: firstSessionId },
173
+ },
174
+ });
175
+
176
+ // Advance time by only 500ms
177
+ jest.setSystemTime(baseTime + 500);
178
+
179
+ // Force expired condition artificially - this should be impossible in real scenarios
180
+ plugin.lastEventTime = baseTime - (MAX_SESSION_TIME_IN_MS + 10000); // MAX_SESSION_TIME_IN_MS + 10 seconds ago, definitely expired
181
+
182
+ // This scenario should NEVER happen in practice, but if it does, it's a bug
183
+ // The current implementation prevents this with a 1000ms guard, masking the bug
184
+ await plugin.execute(mockEvent);
185
+
186
+ // CURRENT BEHAVIOR (with guard): Only one session_start
187
+ // EXPECTED BEHAVIOR (without bugs): Should never reach this scenario
188
+ expect(plugin.analytics?.track).toHaveBeenCalledTimes(1);
189
+
190
+ // This test documents the current guard behavior but highlights it's a bug mask
191
+ console.warn(
192
+ '🐛 BUG MASKED: Multiple session start attempts should never occur'
193
+ );
194
+ });
195
+
196
+ it('BUG: should detect race conditions in parallel event execution', async () => {
197
+ const baseTime = Date.now();
198
+ jest.setSystemTime(baseTime);
199
+
200
+ plugin.sessionId = -1;
201
+ plugin.lastEventTime = -1;
202
+ plugin.resetPending = false;
203
+
204
+ const mockEvents = Array.from({ length: 5 }, (_, i) => ({
205
+ type: EventType.TrackEvent,
206
+ event: `test_event_${i}`,
207
+ properties: {},
208
+ messageId: `msg-${i}`,
209
+ timestamp: '2023-01-01T00:00:00.000Z',
210
+ anonymousId: 'anon-1',
211
+ })) as TrackEventType[];
212
+
213
+ // Execute multiple events in parallel - this could cause race conditions
214
+ const promises = mockEvents.map((event) => plugin.execute(event));
215
+ await Promise.all(promises);
216
+
217
+ // Count session_start calls
218
+ const trackMock = plugin.analytics?.track as jest.Mock;
219
+ const sessionStartCalls = trackMock.mock.calls.filter(
220
+ (call: any) => call[0] === 'session_start'
221
+ );
222
+
223
+ // IDEAL: Should only have 1 session_start call
224
+ // REALITY: May have multiple due to race conditions
225
+ if (sessionStartCalls.length > 1) {
226
+ console.error(
227
+ `🐛 BUG DETECTED: ${sessionStartCalls.length} session_start calls for parallel events`
228
+ );
229
+ // This test will fail if the bug exists, which is expected
230
+ expect(sessionStartCalls).toHaveLength(1);
231
+ } else {
232
+ // If this passes, the implementation handles parallel calls correctly
233
+ expect(sessionStartCalls).toHaveLength(1);
234
+ }
235
+ });
236
+
237
+ // it('BUG: should detect session restart loops from app state changes', async () => {
238
+ // const baseTime = Date.now();
239
+ // jest.setSystemTime(baseTime);
240
+
241
+ // // Start with an active session
242
+ // plugin.sessionId = baseTime;
243
+ // plugin.lastEventTime = baseTime;
244
+
245
+ // // Spy on startNewSessionIfNecessary to detect multiple calls
246
+ // const startNewSessionSpy = jest.spyOn(plugin as any, 'startNewSessionIfNecessary');
247
+ // const endSessionSpy = jest.spyOn(plugin as any, 'endSession');
248
+ // const startSessionSpy = jest.spyOn(plugin as any, 'startNewSession');
249
+
250
+ // // Simulate rapid app state changes
251
+ // const addEventListenerSpy = jest.spyOn(AppState, 'addEventListener');
252
+ // await setupPluginWithClient();
253
+ // const appStateChangeHandler = addEventListenerSpy.mock.calls[0][1];
254
+
255
+ // // Rapid background/foreground cycles
256
+ // appStateChangeHandler('background');
257
+ // appStateChangeHandler('active');
258
+ // appStateChangeHandler('background');
259
+ // appStateChangeHandler('active');
260
+
261
+ // // Wait for any async operations
262
+ // await new Promise(resolve => setTimeout(resolve, 0));
263
+
264
+ // // Should not cause multiple session operations for non-expired session
265
+ // const startNewSessionCalls = startNewSessionSpy.mock.calls.length;
266
+ // const endSessionCalls = endSessionSpy.mock.calls.length;
267
+ // const startSessionCalls = startSessionSpy.mock.calls.length;
268
+
269
+ // if (startNewSessionCalls > 2 || endSessionCalls > 0 || startSessionCalls > 0) {
270
+ // console.error(`🐛 BUG DETECTED: Unnecessary session operations - startNewSessionIfNecessary: ${startNewSessionCalls}, endSession: ${endSessionCalls}, startNewSession: ${startSessionCalls}`);
271
+ // }
272
+
273
+ // // For a non-expired session, we shouldn't have any actual session restarts
274
+ // expect(endSessionCalls).toBe(0);
275
+ // expect(startSessionCalls).toBe(0);
276
+ // });
277
+
278
+ it('BUG: should detect inconsistent session state', async () => {
279
+ const baseTime = Date.now();
280
+ jest.setSystemTime(baseTime);
281
+
282
+ // Set up inconsistent state that should never happen
283
+ plugin.sessionId = baseTime;
284
+ plugin.lastEventTime = -1; // Inconsistent: have sessionId but no lastEventTime
285
+ plugin.resetPending = false;
286
+
287
+ const mockEvent: TrackEventType = {
288
+ type: EventType.TrackEvent,
289
+ event: 'test_event',
290
+ properties: {},
291
+ messageId: 'msg-1',
292
+ timestamp: '2023-01-01T00:00:00.000Z',
293
+ anonymousId: 'anon-1',
294
+ };
295
+
296
+ // This inconsistent state might cause unexpected behavior
297
+ await plugin.execute(mockEvent);
298
+
299
+ // Check if the plugin handled inconsistent state correctly
300
+ const trackMock = plugin.analytics?.track as jest.Mock;
301
+ const sessionStartCalls = trackMock.mock.calls.filter(
302
+ (call: any) => call[0] === 'session_start'
303
+ );
304
+ const sessionEndCalls = trackMock.mock.calls.filter(
305
+ (call: any) => call[0] === 'session_end'
306
+ );
307
+
308
+ // Inconsistent state should be resolved without multiple session events
309
+ if (sessionStartCalls.length > 1 || sessionEndCalls.length > 1) {
310
+ console.error(
311
+ `🐛 BUG DETECTED: Inconsistent state caused multiple session events - starts: ${sessionStartCalls.length}, ends: ${sessionEndCalls.length}`
312
+ );
313
+ }
314
+
315
+ // Should have resolved to a consistent state
316
+ expect(plugin.sessionId).toBeGreaterThan(0);
317
+ expect(plugin.lastEventTime).toBeGreaterThan(0);
318
+ });
319
+
320
+ it('BUG: should detect async race conditions in startNewSessionIfNecessary', async () => {
321
+ const baseTime = Date.now();
322
+ jest.setSystemTime(baseTime);
323
+
324
+ plugin.sessionId = -1;
325
+ plugin.lastEventTime = -1;
326
+
327
+ const mockEvent: TrackEventType = {
328
+ type: EventType.TrackEvent,
329
+ event: 'test_event',
330
+ properties: {},
331
+ messageId: 'msg-1',
332
+ timestamp: '2023-01-01T00:00:00.000Z',
333
+ anonymousId: 'anon-1',
334
+ };
335
+
336
+ // Spy on the async methods to detect overlapping calls
337
+ const startNewSessionIfNecessarySpy = jest.spyOn(
338
+ plugin as any,
339
+ 'startNewSessionIfNecessary'
340
+ );
341
+ const endSessionSpy = jest.spyOn(plugin as any, 'endSession');
342
+ const startNewSessionSpy = jest.spyOn(plugin as any, 'startNewSession');
343
+
344
+ // Call execute multiple times rapidly before any async operations complete
345
+ // This tests if the implementation properly handles concurrent calls to startNewSessionIfNecessary
346
+ const promises = [
347
+ plugin.execute({ ...mockEvent, messageId: 'msg-1' }),
348
+ plugin.execute({ ...mockEvent, messageId: 'msg-2' }),
349
+ plugin.execute({ ...mockEvent, messageId: 'msg-3' }),
350
+ ];
351
+
352
+ await Promise.all(promises);
353
+
354
+ const startNewSessionIfNecessaryCalls =
355
+ startNewSessionIfNecessarySpy.mock.calls.length;
356
+ const endSessionCalls = endSessionSpy.mock.calls.length;
357
+ const startNewSessionCalls = startNewSessionSpy.mock.calls.length;
358
+
359
+ // For initial session creation, we should only have:
360
+ // - Multiple calls to startNewSessionIfNecessary (one per execute)
361
+ // - But only ONE actual startNewSession call
362
+ // - Zero endSession calls (no existing session to end)
363
+
364
+ console.log(
365
+ `📊 Session operations: startNewSessionIfNecessary: ${startNewSessionIfNecessaryCalls}, endSession: ${endSessionCalls}, startNewSession: ${startNewSessionCalls}`
366
+ );
367
+
368
+ if (startNewSessionCalls > 1) {
369
+ console.error(
370
+ `🐛 CRITICAL BUG DETECTED: ${startNewSessionCalls} startNewSession calls from concurrent execute operations`
371
+ );
372
+ // This should fail if there are race conditions
373
+ expect(startNewSessionCalls).toBe(1);
374
+ }
375
+
376
+ if (endSessionCalls > 1) {
377
+ console.error(
378
+ `🐛 BUG DETECTED: ${endSessionCalls} endSession calls from concurrent operations`
379
+ );
380
+ expect(endSessionCalls).toBeLessThanOrEqual(1);
381
+ }
382
+
383
+ // Should have properly created exactly one session
384
+ expect(plugin.sessionId).toBeGreaterThan(0);
385
+ expect(plugin.lastEventTime).toBeGreaterThan(0);
386
+ });
387
+
388
+ it('BUG: should detect overlapping session end/start operations', async () => {
389
+ const baseTime = Date.now();
390
+ jest.setSystemTime(baseTime);
391
+
392
+ // Start with an existing session that will expire
393
+ plugin.sessionId = baseTime - 1000;
394
+ plugin.lastEventTime = baseTime - (MAX_SESSION_TIME_IN_MS + 10000); // MAX_SESSION_TIME_IN_MS + 10 seconds ago, expired
395
+
396
+ const mockEvent: TrackEventType = {
397
+ type: EventType.TrackEvent,
398
+ event: 'test_event',
399
+ properties: {},
400
+ messageId: 'msg-1',
401
+ timestamp: '2023-01-01T00:00:00.000Z',
402
+ anonymousId: 'anon-1',
403
+ };
404
+
405
+ // Spy on session operations
406
+ const endSessionSpy = jest.spyOn(plugin as any, 'endSession');
407
+ const startNewSessionSpy = jest.spyOn(plugin as any, 'startNewSession');
408
+
409
+ // Execute multiple events that should all trigger session restart
410
+ const promises = [
411
+ plugin.execute({ ...mockEvent, messageId: 'msg-1' }),
412
+ plugin.execute({ ...mockEvent, messageId: 'msg-2' }),
413
+ plugin.execute({ ...mockEvent, messageId: 'msg-3' }),
414
+ ];
415
+
416
+ await Promise.all(promises);
417
+
418
+ const endSessionCalls = endSessionSpy.mock.calls.length;
419
+ const startNewSessionCalls = startNewSessionSpy.mock.calls.length;
420
+
421
+ // For session restart, we should have:
422
+ // - Exactly ONE endSession call (to end the expired session)
423
+ // - Exactly ONE startNewSession call (to start the new session)
424
+
425
+ if (endSessionCalls > 1) {
426
+ console.error(
427
+ `🐛 BUG DETECTED: ${endSessionCalls} endSession calls from concurrent operations`
428
+ );
429
+ expect(endSessionCalls).toBe(1);
430
+ }
431
+
432
+ if (startNewSessionCalls > 1) {
433
+ console.error(
434
+ `🐛 CRITICAL BUG DETECTED: ${startNewSessionCalls} startNewSession calls from concurrent operations`
435
+ );
436
+ expect(startNewSessionCalls).toBe(1);
437
+ }
438
+
439
+ // Verify the track calls
440
+ const trackMock = plugin.analytics?.track as jest.Mock;
441
+ const sessionEndCalls = trackMock.mock.calls.filter(
442
+ (call: any) => call[0] === 'session_end'
443
+ );
444
+ const sessionStartCalls = trackMock.mock.calls.filter(
445
+ (call: any) => call[0] === 'session_start'
446
+ );
447
+
448
+ if (sessionEndCalls.length > 1 || sessionStartCalls.length > 1) {
449
+ console.error(
450
+ `🐛 BUG DETECTED: Multiple session events - ends: ${sessionEndCalls.length}, starts: ${sessionStartCalls.length}`
451
+ );
452
+ }
453
+
454
+ expect(sessionEndCalls).toHaveLength(1);
455
+ expect(sessionStartCalls).toHaveLength(1);
456
+ });
457
+
458
+ it('EXPECTED BEHAVIOR: single session for sequential events within session timeout', async () => {
459
+ const baseTime = Date.now();
460
+ jest.setSystemTime(baseTime);
461
+
462
+ plugin.sessionId = -1;
463
+ plugin.lastEventTime = -1;
464
+
465
+ const mockEvents = Array.from({ length: 5 }, (_, i) => ({
466
+ type: EventType.TrackEvent,
467
+ event: `test_event_${i}`,
468
+ properties: {},
469
+ messageId: `msg-${i}`,
470
+ timestamp: '2023-01-01T00:00:00.000Z',
471
+ anonymousId: 'anon-1',
472
+ })) as TrackEventType[];
473
+
474
+ // Execute events sequentially with small time gaps (within session timeout)
475
+ for (let i = 0; i < mockEvents.length; i++) {
476
+ jest.setSystemTime(baseTime + i * 10000); // 10 seconds apart
477
+ await plugin.execute(mockEvents[i]);
478
+ }
479
+
480
+ // Should only have one session_start call for all events
481
+ const trackMock = plugin.analytics?.track as jest.Mock;
482
+ const sessionStartCalls = trackMock.mock.calls.filter(
483
+ (call: any) => call[0] === 'session_start'
484
+ );
485
+
486
+ expect(sessionStartCalls).toHaveLength(1);
487
+
488
+ // All events should have the same session ID
489
+ const sessionId = plugin.sessionId;
490
+ expect(sessionId).toBeGreaterThan(0);
491
+ });
492
+ });
493
+
494
+ describe('session expiration scenarios', () => {
495
+ beforeEach(async () => {
496
+ await setupPluginWithClient();
497
+ });
498
+
499
+ it('should expire session exactly at MAX_SESSION_TIME_IN_MS', async () => {
500
+ const baseTime = Date.now();
501
+ jest.setSystemTime(baseTime);
502
+
503
+ plugin.sessionId = baseTime - 1000;
504
+ plugin.lastEventTime = baseTime - MAX_SESSION_TIME_IN_MS; // Exactly 60 seconds
505
+ plugin.resetPending = false;
506
+
507
+ const mockEvent: TrackEventType = {
508
+ type: EventType.TrackEvent,
509
+ event: 'test_event',
510
+ properties: {},
511
+ messageId: 'msg-1',
512
+ timestamp: '2023-01-01T00:00:00.000Z',
513
+ anonymousId: 'anon-1',
514
+ };
515
+
516
+ const oldSessionId = plugin.sessionId;
517
+ await plugin.execute(mockEvent);
518
+
519
+ expect(plugin.sessionId).not.toBe(oldSessionId);
520
+ expect(plugin.analytics?.track).toHaveBeenCalledWith('session_end', {
521
+ integrations: {
522
+ 'Actions Amplitude': { session_id: oldSessionId },
523
+ },
524
+ });
525
+ });
526
+
527
+ it('should NOT expire session at MAX_SESSION_TIME_IN_MS - 1 second', async () => {
528
+ // ✅ Freeze Date.now for this test only
529
+ const fixedNow = 1761550980000;
530
+ const nowSpy = jest.spyOn(Date, 'now').mockImplementation(() => fixedNow);
531
+
532
+ plugin.sessionId = fixedNow - 1000;
533
+ plugin.lastEventTime = fixedNow - (MAX_SESSION_TIME_IN_MS - 2); // within limit
534
+
535
+ const mockEvent: TrackEventType = {
536
+ type: EventType.TrackEvent,
537
+ event: 'test_event',
538
+ properties: {},
539
+ messageId: 'msg-1',
540
+ timestamp: '2023-01-01T00:00:00.000Z',
541
+ anonymousId: 'anon-1',
542
+ };
543
+
544
+ const oldSessionId = plugin.sessionId;
545
+
546
+ await plugin.execute(mockEvent);
547
+
548
+ expect(plugin.sessionId).toBe(oldSessionId);
549
+ expect(plugin.analytics?.track).not.toHaveBeenCalledWith(
550
+ 'session_start',
551
+ expect.any(Object)
552
+ );
553
+ expect(plugin.analytics?.track).not.toHaveBeenCalledWith(
554
+ 'session_end',
555
+ expect.any(Object)
556
+ );
557
+
558
+ nowSpy.mockRestore(); // ✅ restores Date.now, unaffected by useRealTimers
559
+ });
560
+ });
561
+
562
+ describe('app state change scenarios', () => {
563
+ let appStateChangeHandler: (nextAppState: any) => void;
564
+
565
+ beforeEach(async () => {
566
+ // Spy on AppState methods
567
+ const addEventListenerSpy = jest.spyOn(AppState, 'addEventListener');
568
+
569
+ await setupPluginWithClient();
570
+
571
+ // Capture the app state change handler
572
+ expect(addEventListenerSpy).toHaveBeenCalledWith(
573
+ 'change',
574
+ expect.any(Function)
575
+ );
576
+ appStateChangeHandler = addEventListenerSpy.mock.calls[0][1];
577
+ });
578
+
579
+ it('should start new session when app comes to foreground after expiration', async () => {
580
+ const baseTime = Date.now();
581
+ jest.setSystemTime(baseTime);
582
+
583
+ // Set up an active session that will be expired
584
+ plugin.sessionId = baseTime - 1000;
585
+ plugin.lastEventTime = baseTime - (MAX_SESSION_TIME_IN_MS + 10000); // MAX_SESSION_TIME_IN_MS + 10 seconds ago, already expired
586
+
587
+ // Spy on the startNewSessionIfNecessary method to ensure it gets called
588
+ const startNewSessionSpy = jest.spyOn(
589
+ plugin as any,
590
+ 'startNewSessionIfNecessary'
591
+ );
592
+
593
+ // Simulate app coming to foreground
594
+ appStateChangeHandler('active');
595
+
596
+ // Should call startNewSessionIfNecessary
597
+ expect(startNewSessionSpy).toHaveBeenCalled();
598
+ });
599
+
600
+ it('should NOT start new session when app comes to foreground before expiration', async () => {
601
+ const baseTime = Date.now();
602
+ jest.setSystemTime(baseTime);
603
+
604
+ // Set up an active session
605
+ plugin.sessionId = baseTime - 1000;
606
+ plugin.lastEventTime = baseTime - 30000; // 30 seconds ago, still active
607
+
608
+ // Simulate app going to background
609
+ appStateChangeHandler('background');
610
+
611
+ // Advance time but not beyond session timeout
612
+ jest.setSystemTime(baseTime + 20000); // 20 seconds later (total 50 seconds)
613
+
614
+ // Simulate app coming to foreground
615
+ appStateChangeHandler('active');
616
+
617
+ // Should NOT trigger new session
618
+ expect(plugin.analytics?.track).not.toHaveBeenCalled();
619
+ });
620
+
621
+ it('should update lastEventTime when app goes to background', async () => {
622
+ const baseTime = Date.now();
623
+ jest.setSystemTime(baseTime);
624
+
625
+ plugin.sessionId = baseTime - 1000;
626
+ plugin.lastEventTime = baseTime - 30000;
627
+
628
+ // Simulate app going to background
629
+ appStateChangeHandler('background');
630
+
631
+ expect(plugin.lastEventTime).toBe(baseTime);
632
+ expect(mockAsyncStorage.setItem).toHaveBeenCalled();
633
+ });
634
+ });
635
+
636
+ describe('session data persistence', () => {
637
+ it('should load session data from AsyncStorage on configure', async () => {
638
+ const mockSessionId = '1234567890';
639
+ const mockLastEventTime = '1234567000';
640
+
641
+ mockAsyncStorage.getItem
642
+ .mockResolvedValueOnce(mockSessionId) // SESSION_ID_KEY
643
+ .mockResolvedValueOnce(mockLastEventTime); // LAST_EVENT_TIME_KEY
644
+
645
+ const mockClient = { track: jest.fn() } as any;
646
+ await plugin.configure(mockClient);
647
+
648
+ expect(plugin.sessionId).toBe(1234567890);
649
+ expect(plugin.lastEventTime).toBe(1234567000);
650
+ });
651
+
652
+ it('should save session data to AsyncStorage after events', async () => {
653
+ await setupPluginWithClient();
654
+
655
+ const mockEvent: TrackEventType = {
656
+ type: EventType.TrackEvent,
657
+ event: 'test_event',
658
+ properties: {},
659
+ messageId: 'msg-1',
660
+ timestamp: '2023-01-01T00:00:00.000Z',
661
+ anonymousId: 'anon-1',
662
+ };
663
+
664
+ await plugin.execute(mockEvent);
665
+
666
+ expect(mockAsyncStorage.setItem).toHaveBeenCalledWith(
667
+ 'event_session_id',
668
+ plugin.sessionId.toString()
669
+ );
670
+ expect(mockAsyncStorage.setItem).toHaveBeenCalledWith(
671
+ 'last_event_time',
672
+ plugin.lastEventTime.toString()
673
+ );
674
+ });
675
+
676
+ it('should clear session data on reset', async () => {
677
+ await setupPluginWithClient();
678
+
679
+ await plugin.reset();
680
+
681
+ expect(plugin.sessionId).toBe(-1);
682
+ expect(plugin.lastEventTime).toBe(-1);
683
+ expect(plugin.eventSessionId).toBe(-1);
684
+ expect(mockAsyncStorage.removeItem).toHaveBeenCalledWith(
685
+ 'previous_session_id'
686
+ );
687
+ });
688
+ });
689
+
690
+ describe('event enrichment', () => {
691
+ beforeEach(async () => {
692
+ await setupPluginWithClient();
693
+ });
694
+
695
+ it('should add session_id to track events', async () => {
696
+ const mockEvent: TrackEventType = {
697
+ type: EventType.TrackEvent,
698
+ event: 'test_event',
699
+ properties: {},
700
+ messageId: 'msg-1',
701
+ timestamp: '2023-01-01T00:00:00.000Z',
702
+ anonymousId: 'anon-1',
703
+ };
704
+
705
+ const result = await plugin.execute(mockEvent);
706
+
707
+ expect(result.integrations?.['Actions Amplitude']).toEqual({
708
+ session_id: plugin.sessionId,
709
+ });
710
+ });
711
+
712
+ it('should add session_id to identify events', async () => {
713
+ const mockEvent: IdentifyEventType = {
714
+ type: EventType.IdentifyEvent,
715
+ traits: {},
716
+ messageId: 'msg-1',
717
+ timestamp: '2023-01-01T00:00:00.000Z',
718
+ anonymousId: 'anon-1',
719
+ };
720
+
721
+ const result = await plugin.execute(mockEvent);
722
+
723
+ expect(result.integrations?.['Actions Amplitude']).toEqual({
724
+ session_id: plugin.sessionId,
725
+ });
726
+ });
727
+
728
+ it('should add name property to screen events', async () => {
729
+ const mockEvent: ScreenEventType = {
730
+ type: EventType.ScreenEvent,
731
+ name: 'Home Screen',
732
+ properties: { existing: 'prop' },
733
+ messageId: 'msg-1',
734
+ timestamp: '2023-01-01T00:00:00.000Z',
735
+ anonymousId: 'anon-1',
736
+ };
737
+
738
+ const result = (await plugin.execute(mockEvent)) as ScreenEventType;
739
+
740
+ expect(result.properties).toEqual({
741
+ existing: 'prop',
742
+ name: 'Home Screen',
743
+ });
744
+ expect(result.integrations?.['Actions Amplitude']).toEqual({
745
+ session_id: plugin.sessionId,
746
+ });
747
+ });
748
+
749
+ it('should NOT modify events when session_id already exists', async () => {
750
+ const mockEvent: TrackEventType = {
751
+ type: EventType.TrackEvent,
752
+ event: 'test_event',
753
+ properties: {},
754
+ messageId: 'msg-1',
755
+ timestamp: '2023-01-01T00:00:00.000Z',
756
+ anonymousId: 'anon-1',
757
+ integrations: {
758
+ 'Actions Amplitude': { session_id: 999999 },
759
+ },
760
+ };
761
+
762
+ const result = await plugin.execute(mockEvent);
763
+
764
+ expect(result.integrations?.['Actions Amplitude']).toEqual({
765
+ session_id: 999999, // Should preserve existing session_id
766
+ });
767
+ });
768
+ });
769
+ });