react-native-nitro-amplitude 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (411) hide show
  1. package/.watchmanconfig +6 -0
  2. package/LICENSE +21 -0
  3. package/README.md +139 -0
  4. package/android/CMakeLists.txt +34 -0
  5. package/android/build.gradle +85 -0
  6. package/android/consumer-rules.pro +35 -0
  7. package/android/gradle.properties +4 -0
  8. package/android/src/main/cpp/AndroidAmplitudeAdapterCpp.cpp +126 -0
  9. package/android/src/main/cpp/AndroidAmplitudeAdapterCpp.hpp +48 -0
  10. package/android/src/main/cpp/cpp-adapter.cpp +9 -0
  11. package/android/src/main/java/com/nitroamplitude/AndroidAmplitudeAdapter.kt +147 -0
  12. package/android/src/main/java/com/nitroamplitude/NitroAmplitudePackage.kt +24 -0
  13. package/app.plugin.js +36 -0
  14. package/cpp/bindings/HybridAmplitudeContext.cpp +83 -0
  15. package/cpp/bindings/HybridAmplitudeContext.hpp +29 -0
  16. package/cpp/bindings/HybridAmplitudeStorage.cpp +163 -0
  17. package/cpp/bindings/HybridAmplitudeStorage.hpp +38 -0
  18. package/cpp/bindings/HybridAmplitudeWorker.cpp +162 -0
  19. package/cpp/bindings/HybridAmplitudeWorker.hpp +74 -0
  20. package/cpp/core/NativeAmplitudeAdapter.hpp +44 -0
  21. package/ios/IOSAmplitudeAdapterCpp.hpp +37 -0
  22. package/ios/IOSAmplitudeAdapterCpp.mm +155 -0
  23. package/lib/commonjs/AmplitudeContext.nitro.js +6 -0
  24. package/lib/commonjs/AmplitudeContext.nitro.js.map +1 -0
  25. package/lib/commonjs/AmplitudeStorage.nitro.js +6 -0
  26. package/lib/commonjs/AmplitudeStorage.nitro.js.map +1 -0
  27. package/lib/commonjs/AmplitudeWorker.nitro.js +6 -0
  28. package/lib/commonjs/AmplitudeWorker.nitro.js.map +1 -0
  29. package/lib/commonjs/analytics/campaign/campaign-tracker.js +105 -0
  30. package/lib/commonjs/analytics/campaign/campaign-tracker.js.map +1 -0
  31. package/lib/commonjs/analytics/campaign/types.js +6 -0
  32. package/lib/commonjs/analytics/campaign/types.js.map +1 -0
  33. package/lib/commonjs/analytics/config.js +283 -0
  34. package/lib/commonjs/analytics/config.js.map +1 -0
  35. package/lib/commonjs/analytics/cookie-migration/index.js +59 -0
  36. package/lib/commonjs/analytics/cookie-migration/index.js.map +1 -0
  37. package/lib/commonjs/analytics/index.js +95 -0
  38. package/lib/commonjs/analytics/index.js.map +1 -0
  39. package/lib/commonjs/analytics/migration/remnant-data-migration.js +177 -0
  40. package/lib/commonjs/analytics/migration/remnant-data-migration.js.map +1 -0
  41. package/lib/commonjs/analytics/nitro-transport.js +31 -0
  42. package/lib/commonjs/analytics/nitro-transport.js.map +1 -0
  43. package/lib/commonjs/analytics/plugins/context.js +140 -0
  44. package/lib/commonjs/analytics/plugins/context.js.map +1 -0
  45. package/lib/commonjs/analytics/react-native-client.js +352 -0
  46. package/lib/commonjs/analytics/react-native-client.js.map +1 -0
  47. package/lib/commonjs/analytics/storage/local-storage.js +73 -0
  48. package/lib/commonjs/analytics/storage/local-storage.js.map +1 -0
  49. package/lib/commonjs/analytics/types.js +175 -0
  50. package/lib/commonjs/analytics/types.js.map +1 -0
  51. package/lib/commonjs/analytics/typings/browser-snippet.d.js +6 -0
  52. package/lib/commonjs/analytics/typings/browser-snippet.d.js.map +1 -0
  53. package/lib/commonjs/analytics/typings/ua-parser.d.js +2 -0
  54. package/lib/commonjs/analytics/typings/ua-parser.d.js.map +1 -0
  55. package/lib/commonjs/analytics/utils/platform.js +16 -0
  56. package/lib/commonjs/analytics/utils/platform.js.map +1 -0
  57. package/lib/commonjs/analytics/version.js +8 -0
  58. package/lib/commonjs/analytics/version.js.map +1 -0
  59. package/lib/commonjs/experiment/experimentClient.js +792 -0
  60. package/lib/commonjs/experiment/experimentClient.js.map +1 -0
  61. package/lib/commonjs/experiment/factory.js +77 -0
  62. package/lib/commonjs/experiment/factory.js.map +1 -0
  63. package/lib/commonjs/experiment/gen/version.js +9 -0
  64. package/lib/commonjs/experiment/gen/version.js.map +1 -0
  65. package/lib/commonjs/experiment/index.js +143 -0
  66. package/lib/commonjs/experiment/index.js.map +1 -0
  67. package/lib/commonjs/experiment/integration/NativeExperimentReactNativeClient.js +11 -0
  68. package/lib/commonjs/experiment/integration/NativeExperimentReactNativeClient.js.map +1 -0
  69. package/lib/commonjs/experiment/integration/connector.js +67 -0
  70. package/lib/commonjs/experiment/integration/connector.js.map +1 -0
  71. package/lib/commonjs/experiment/integration/default.js +92 -0
  72. package/lib/commonjs/experiment/integration/default.js.map +1 -0
  73. package/lib/commonjs/experiment/logger/ampLogger.js +80 -0
  74. package/lib/commonjs/experiment/logger/ampLogger.js.map +1 -0
  75. package/lib/commonjs/experiment/logger/consoleLogger.js +60 -0
  76. package/lib/commonjs/experiment/logger/consoleLogger.js.map +1 -0
  77. package/lib/commonjs/experiment/storage/cache.js +197 -0
  78. package/lib/commonjs/experiment/storage/cache.js.map +1 -0
  79. package/lib/commonjs/experiment/storage/local-storage.js +25 -0
  80. package/lib/commonjs/experiment/storage/local-storage.js.map +1 -0
  81. package/lib/commonjs/experiment/stubClient.js +46 -0
  82. package/lib/commonjs/experiment/stubClient.js.map +1 -0
  83. package/lib/commonjs/experiment/transport/http.js +72 -0
  84. package/lib/commonjs/experiment/transport/http.js.map +1 -0
  85. package/lib/commonjs/experiment/types/client.js +6 -0
  86. package/lib/commonjs/experiment/types/client.js.map +1 -0
  87. package/lib/commonjs/experiment/types/config.js +67 -0
  88. package/lib/commonjs/experiment/types/config.js.map +1 -0
  89. package/lib/commonjs/experiment/types/exposure.js +2 -0
  90. package/lib/commonjs/experiment/types/exposure.js.map +1 -0
  91. package/lib/commonjs/experiment/types/logger.js +42 -0
  92. package/lib/commonjs/experiment/types/logger.js.map +1 -0
  93. package/lib/commonjs/experiment/types/source.js +54 -0
  94. package/lib/commonjs/experiment/types/source.js.map +1 -0
  95. package/lib/commonjs/experiment/types/storage.js +2 -0
  96. package/lib/commonjs/experiment/types/storage.js.map +1 -0
  97. package/lib/commonjs/experiment/types/transport.js +2 -0
  98. package/lib/commonjs/experiment/types/transport.js.map +1 -0
  99. package/lib/commonjs/experiment/types/user.js +2 -0
  100. package/lib/commonjs/experiment/types/user.js.map +1 -0
  101. package/lib/commonjs/experiment/types/variant.js +2 -0
  102. package/lib/commonjs/experiment/types/variant.js.map +1 -0
  103. package/lib/commonjs/experiment/util/backoff.js +54 -0
  104. package/lib/commonjs/experiment/util/backoff.js.map +1 -0
  105. package/lib/commonjs/experiment/util/base64.js +23 -0
  106. package/lib/commonjs/experiment/util/base64.js.map +1 -0
  107. package/lib/commonjs/experiment/util/convert.js +78 -0
  108. package/lib/commonjs/experiment/util/convert.js.map +1 -0
  109. package/lib/commonjs/experiment/util/index.js +25 -0
  110. package/lib/commonjs/experiment/util/index.js.map +1 -0
  111. package/lib/commonjs/experiment/util/platform.js +16 -0
  112. package/lib/commonjs/experiment/util/platform.js.map +1 -0
  113. package/lib/commonjs/experiment/util/randomstring.js +16 -0
  114. package/lib/commonjs/experiment/util/randomstring.js.map +1 -0
  115. package/lib/commonjs/experiment/util/userSessionExposureTracker.js +40 -0
  116. package/lib/commonjs/experiment/util/userSessionExposureTracker.js.map +1 -0
  117. package/lib/commonjs/index.js +298 -0
  118. package/lib/commonjs/index.js.map +1 -0
  119. package/lib/commonjs/index.web.js +22 -0
  120. package/lib/commonjs/index.web.js.map +1 -0
  121. package/lib/commonjs/native/context.js +43 -0
  122. package/lib/commonjs/native/context.js.map +1 -0
  123. package/lib/commonjs/native/http.js +62 -0
  124. package/lib/commonjs/native/http.js.map +1 -0
  125. package/lib/commonjs/native/hybrid.js +31 -0
  126. package/lib/commonjs/native/hybrid.js.map +1 -0
  127. package/lib/commonjs/native/storage.js +93 -0
  128. package/lib/commonjs/native/storage.js.map +1 -0
  129. package/lib/commonjs/package.json +1 -0
  130. package/lib/module/AmplitudeContext.nitro.js +4 -0
  131. package/lib/module/AmplitudeContext.nitro.js.map +1 -0
  132. package/lib/module/AmplitudeStorage.nitro.js +4 -0
  133. package/lib/module/AmplitudeStorage.nitro.js.map +1 -0
  134. package/lib/module/AmplitudeWorker.nitro.js +4 -0
  135. package/lib/module/AmplitudeWorker.nitro.js.map +1 -0
  136. package/lib/module/analytics/campaign/campaign-tracker.js +100 -0
  137. package/lib/module/analytics/campaign/campaign-tracker.js.map +1 -0
  138. package/lib/module/analytics/campaign/types.js +4 -0
  139. package/lib/module/analytics/campaign/types.js.map +1 -0
  140. package/lib/module/analytics/config.js +272 -0
  141. package/lib/module/analytics/config.js.map +1 -0
  142. package/lib/module/analytics/cookie-migration/index.js +51 -0
  143. package/lib/module/analytics/cookie-migration/index.js.map +1 -0
  144. package/lib/module/analytics/index.js +34 -0
  145. package/lib/module/analytics/index.js.map +1 -0
  146. package/lib/module/analytics/migration/remnant-data-migration.js +172 -0
  147. package/lib/module/analytics/migration/remnant-data-migration.js.map +1 -0
  148. package/lib/module/analytics/nitro-transport.js +26 -0
  149. package/lib/module/analytics/nitro-transport.js.map +1 -0
  150. package/lib/module/analytics/plugins/context.js +134 -0
  151. package/lib/module/analytics/plugins/context.js.map +1 -0
  152. package/lib/module/analytics/react-native-client.js +346 -0
  153. package/lib/module/analytics/react-native-client.js.map +1 -0
  154. package/lib/module/analytics/storage/local-storage.js +68 -0
  155. package/lib/module/analytics/storage/local-storage.js.map +1 -0
  156. package/lib/module/analytics/types.js +4 -0
  157. package/lib/module/analytics/types.js.map +1 -0
  158. package/lib/module/analytics/typings/browser-snippet.d.js +4 -0
  159. package/lib/module/analytics/typings/browser-snippet.d.js.map +1 -0
  160. package/lib/module/analytics/typings/ua-parser.d.js +2 -0
  161. package/lib/module/analytics/typings/ua-parser.d.js.map +1 -0
  162. package/lib/module/analytics/utils/platform.js +10 -0
  163. package/lib/module/analytics/utils/platform.js.map +1 -0
  164. package/lib/module/analytics/version.js +4 -0
  165. package/lib/module/analytics/version.js.map +1 -0
  166. package/lib/module/experiment/experimentClient.js +788 -0
  167. package/lib/module/experiment/experimentClient.js.map +1 -0
  168. package/lib/module/experiment/factory.js +73 -0
  169. package/lib/module/experiment/factory.js.map +1 -0
  170. package/lib/module/experiment/gen/version.js +5 -0
  171. package/lib/module/experiment/gen/version.js.map +1 -0
  172. package/lib/module/experiment/index.js +16 -0
  173. package/lib/module/experiment/index.js.map +1 -0
  174. package/lib/module/experiment/integration/NativeExperimentReactNativeClient.js +7 -0
  175. package/lib/module/experiment/integration/NativeExperimentReactNativeClient.js.map +1 -0
  176. package/lib/module/experiment/integration/connector.js +61 -0
  177. package/lib/module/experiment/integration/connector.js.map +1 -0
  178. package/lib/module/experiment/integration/default.js +87 -0
  179. package/lib/module/experiment/integration/default.js.map +1 -0
  180. package/lib/module/experiment/logger/ampLogger.js +76 -0
  181. package/lib/module/experiment/logger/ampLogger.js.map +1 -0
  182. package/lib/module/experiment/logger/consoleLogger.js +55 -0
  183. package/lib/module/experiment/logger/consoleLogger.js.map +1 -0
  184. package/lib/module/experiment/storage/cache.js +187 -0
  185. package/lib/module/experiment/storage/cache.js.map +1 -0
  186. package/lib/module/experiment/storage/local-storage.js +19 -0
  187. package/lib/module/experiment/storage/local-storage.js.map +1 -0
  188. package/lib/module/experiment/stubClient.js +41 -0
  189. package/lib/module/experiment/stubClient.js.map +1 -0
  190. package/lib/module/experiment/transport/http.js +66 -0
  191. package/lib/module/experiment/transport/http.js.map +1 -0
  192. package/lib/module/experiment/types/client.js +4 -0
  193. package/lib/module/experiment/types/client.js.map +1 -0
  194. package/lib/module/experiment/types/config.js +64 -0
  195. package/lib/module/experiment/types/config.js.map +1 -0
  196. package/lib/module/experiment/types/exposure.js +2 -0
  197. package/lib/module/experiment/types/exposure.js.map +1 -0
  198. package/lib/module/experiment/types/logger.js +39 -0
  199. package/lib/module/experiment/types/logger.js.map +1 -0
  200. package/lib/module/experiment/types/source.js +51 -0
  201. package/lib/module/experiment/types/source.js.map +1 -0
  202. package/lib/module/experiment/types/storage.js +2 -0
  203. package/lib/module/experiment/types/storage.js.map +1 -0
  204. package/lib/module/experiment/types/transport.js +2 -0
  205. package/lib/module/experiment/types/transport.js.map +1 -0
  206. package/lib/module/experiment/types/user.js +2 -0
  207. package/lib/module/experiment/types/user.js.map +1 -0
  208. package/lib/module/experiment/types/variant.js +2 -0
  209. package/lib/module/experiment/types/variant.js.map +1 -0
  210. package/lib/module/experiment/util/backoff.js +49 -0
  211. package/lib/module/experiment/util/backoff.js.map +1 -0
  212. package/lib/module/experiment/util/base64.js +16 -0
  213. package/lib/module/experiment/util/base64.js.map +1 -0
  214. package/lib/module/experiment/util/convert.js +71 -0
  215. package/lib/module/experiment/util/convert.js.map +1 -0
  216. package/lib/module/experiment/util/index.js +17 -0
  217. package/lib/module/experiment/util/index.js.map +1 -0
  218. package/lib/module/experiment/util/platform.js +10 -0
  219. package/lib/module/experiment/util/platform.js.map +1 -0
  220. package/lib/module/experiment/util/randomstring.js +11 -0
  221. package/lib/module/experiment/util/randomstring.js.map +1 -0
  222. package/lib/module/experiment/util/userSessionExposureTracker.js +35 -0
  223. package/lib/module/experiment/util/userSessionExposureTracker.js.map +1 -0
  224. package/lib/module/index.js +50 -0
  225. package/lib/module/index.js.map +1 -0
  226. package/lib/module/index.web.js +14 -0
  227. package/lib/module/index.web.js.map +1 -0
  228. package/lib/module/native/context.js +35 -0
  229. package/lib/module/native/context.js.map +1 -0
  230. package/lib/module/native/http.js +57 -0
  231. package/lib/module/native/http.js.map +1 -0
  232. package/lib/module/native/hybrid.js +24 -0
  233. package/lib/module/native/hybrid.js.map +1 -0
  234. package/lib/module/native/storage.js +86 -0
  235. package/lib/module/native/storage.js.map +1 -0
  236. package/lib/typescript/AmplitudeContext.nitro.d.ts +17 -0
  237. package/lib/typescript/AmplitudeContext.nitro.d.ts.map +1 -0
  238. package/lib/typescript/AmplitudeStorage.nitro.d.ts +17 -0
  239. package/lib/typescript/AmplitudeStorage.nitro.d.ts.map +1 -0
  240. package/lib/typescript/AmplitudeWorker.nitro.d.ts +11 -0
  241. package/lib/typescript/AmplitudeWorker.nitro.d.ts.map +1 -0
  242. package/lib/typescript/analytics/campaign/campaign-tracker.d.ts +85 -0
  243. package/lib/typescript/analytics/campaign/campaign-tracker.d.ts.map +1 -0
  244. package/lib/typescript/analytics/campaign/types.d.ts +11 -0
  245. package/lib/typescript/analytics/campaign/types.d.ts.map +1 -0
  246. package/lib/typescript/analytics/config.d.ts +68 -0
  247. package/lib/typescript/analytics/config.d.ts.map +1 -0
  248. package/lib/typescript/analytics/cookie-migration/index.d.ts +6 -0
  249. package/lib/typescript/analytics/cookie-migration/index.d.ts.map +1 -0
  250. package/lib/typescript/analytics/index.d.ts +7 -0
  251. package/lib/typescript/analytics/index.d.ts.map +1 -0
  252. package/lib/typescript/analytics/migration/remnant-data-migration.d.ts +20 -0
  253. package/lib/typescript/analytics/migration/remnant-data-migration.d.ts.map +1 -0
  254. package/lib/typescript/analytics/nitro-transport.d.ts +9 -0
  255. package/lib/typescript/analytics/nitro-transport.d.ts.map +1 -0
  256. package/lib/typescript/analytics/plugins/context.d.ts +14 -0
  257. package/lib/typescript/analytics/plugins/context.d.ts.map +1 -0
  258. package/lib/typescript/analytics/react-native-client.d.ts +55 -0
  259. package/lib/typescript/analytics/react-native-client.d.ts.map +1 -0
  260. package/lib/typescript/analytics/storage/local-storage.d.ts +14 -0
  261. package/lib/typescript/analytics/storage/local-storage.d.ts.map +1 -0
  262. package/lib/typescript/analytics/types.d.ts +2 -0
  263. package/lib/typescript/analytics/types.d.ts.map +1 -0
  264. package/lib/typescript/analytics/utils/platform.d.ts +3 -0
  265. package/lib/typescript/analytics/utils/platform.d.ts.map +1 -0
  266. package/lib/typescript/analytics/version.d.ts +2 -0
  267. package/lib/typescript/analytics/version.d.ts.map +1 -0
  268. package/lib/typescript/experiment/experimentClient.d.ts +234 -0
  269. package/lib/typescript/experiment/experimentClient.d.ts.map +1 -0
  270. package/lib/typescript/experiment/factory.d.ts +11 -0
  271. package/lib/typescript/experiment/factory.d.ts.map +1 -0
  272. package/lib/typescript/experiment/gen/version.d.ts +2 -0
  273. package/lib/typescript/experiment/gen/version.d.ts.map +1 -0
  274. package/lib/typescript/experiment/index.d.ts +15 -0
  275. package/lib/typescript/experiment/index.d.ts.map +1 -0
  276. package/lib/typescript/experiment/integration/NativeExperimentReactNativeClient.d.ts +16 -0
  277. package/lib/typescript/experiment/integration/NativeExperimentReactNativeClient.d.ts.map +1 -0
  278. package/lib/typescript/experiment/integration/connector.d.ts +16 -0
  279. package/lib/typescript/experiment/integration/connector.d.ts.map +1 -0
  280. package/lib/typescript/experiment/integration/default.d.ts +20 -0
  281. package/lib/typescript/experiment/integration/default.d.ts.map +1 -0
  282. package/lib/typescript/experiment/logger/ampLogger.d.ts +47 -0
  283. package/lib/typescript/experiment/logger/ampLogger.d.ts.map +1 -0
  284. package/lib/typescript/experiment/logger/consoleLogger.d.ts +40 -0
  285. package/lib/typescript/experiment/logger/consoleLogger.d.ts.map +1 -0
  286. package/lib/typescript/experiment/storage/cache.d.ts +35 -0
  287. package/lib/typescript/experiment/storage/cache.d.ts.map +1 -0
  288. package/lib/typescript/experiment/storage/local-storage.d.ts +11 -0
  289. package/lib/typescript/experiment/storage/local-storage.d.ts.map +1 -0
  290. package/lib/typescript/experiment/stubClient.d.ts +21 -0
  291. package/lib/typescript/experiment/stubClient.d.ts.map +1 -0
  292. package/lib/typescript/experiment/transport/http.d.ts +17 -0
  293. package/lib/typescript/experiment/transport/http.d.ts.map +1 -0
  294. package/lib/typescript/experiment/types/client.d.ts +36 -0
  295. package/lib/typescript/experiment/types/client.d.ts.map +1 -0
  296. package/lib/typescript/experiment/types/config.d.ts +164 -0
  297. package/lib/typescript/experiment/types/config.d.ts.map +1 -0
  298. package/lib/typescript/experiment/types/exposure.d.ts +107 -0
  299. package/lib/typescript/experiment/types/exposure.d.ts.map +1 -0
  300. package/lib/typescript/experiment/types/logger.d.ts +67 -0
  301. package/lib/typescript/experiment/types/logger.d.ts.map +1 -0
  302. package/lib/typescript/experiment/types/source.d.ts +43 -0
  303. package/lib/typescript/experiment/types/source.d.ts.map +1 -0
  304. package/lib/typescript/experiment/types/storage.d.ts +7 -0
  305. package/lib/typescript/experiment/types/storage.d.ts.map +1 -0
  306. package/lib/typescript/experiment/types/transport.d.ts +8 -0
  307. package/lib/typescript/experiment/types/transport.d.ts.map +1 -0
  308. package/lib/typescript/experiment/types/user.d.ts +106 -0
  309. package/lib/typescript/experiment/types/user.d.ts.map +1 -0
  310. package/lib/typescript/experiment/types/variant.d.ts +33 -0
  311. package/lib/typescript/experiment/types/variant.d.ts.map +1 -0
  312. package/lib/typescript/experiment/util/backoff.d.ts +14 -0
  313. package/lib/typescript/experiment/util/backoff.d.ts.map +1 -0
  314. package/lib/typescript/experiment/util/base64.d.ts +3 -0
  315. package/lib/typescript/experiment/util/base64.d.ts.map +1 -0
  316. package/lib/typescript/experiment/util/convert.d.ts +7 -0
  317. package/lib/typescript/experiment/util/convert.d.ts.map +1 -0
  318. package/lib/typescript/experiment/util/index.d.ts +6 -0
  319. package/lib/typescript/experiment/util/index.d.ts.map +1 -0
  320. package/lib/typescript/experiment/util/platform.d.ts +3 -0
  321. package/lib/typescript/experiment/util/platform.d.ts.map +1 -0
  322. package/lib/typescript/experiment/util/randomstring.d.ts +2 -0
  323. package/lib/typescript/experiment/util/randomstring.d.ts.map +1 -0
  324. package/lib/typescript/experiment/util/userSessionExposureTracker.d.ts +16 -0
  325. package/lib/typescript/experiment/util/userSessionExposureTracker.d.ts.map +1 -0
  326. package/lib/typescript/index.d.ts +31 -0
  327. package/lib/typescript/index.d.ts.map +1 -0
  328. package/lib/typescript/index.web.d.ts +12 -0
  329. package/lib/typescript/index.web.d.ts.map +1 -0
  330. package/lib/typescript/native/context.d.ts +29 -0
  331. package/lib/typescript/native/context.d.ts.map +1 -0
  332. package/lib/typescript/native/http.d.ts +6 -0
  333. package/lib/typescript/native/http.d.ts.map +1 -0
  334. package/lib/typescript/native/hybrid.d.ts +8 -0
  335. package/lib/typescript/native/hybrid.d.ts.map +1 -0
  336. package/lib/typescript/native/storage.d.ts +29 -0
  337. package/lib/typescript/native/storage.d.ts.map +1 -0
  338. package/nitro.json +33 -0
  339. package/nitrogen/generated/.gitattributes +1 -0
  340. package/nitrogen/generated/android/NitroAmplitude+autolinking.cmake +83 -0
  341. package/nitrogen/generated/android/NitroAmplitude+autolinking.gradle +27 -0
  342. package/nitrogen/generated/android/NitroAmplitudeOnLoad.cpp +69 -0
  343. package/nitrogen/generated/android/NitroAmplitudeOnLoad.hpp +34 -0
  344. package/nitrogen/generated/android/kotlin/com/margelo/nitro/com/nitroamplitude/NitroAmplitudeOnLoad.kt +35 -0
  345. package/nitrogen/generated/ios/NitroAmplitude+autolinking.rb +62 -0
  346. package/nitrogen/generated/ios/NitroAmplitude-Swift-Cxx-Bridge.cpp +17 -0
  347. package/nitrogen/generated/ios/NitroAmplitude-Swift-Cxx-Bridge.hpp +27 -0
  348. package/nitrogen/generated/ios/NitroAmplitude-Swift-Cxx-Umbrella.hpp +38 -0
  349. package/nitrogen/generated/ios/NitroAmplitudeAutolinking.mm +55 -0
  350. package/nitrogen/generated/ios/NitroAmplitudeAutolinking.swift +16 -0
  351. package/nitrogen/generated/shared/c++/HybridAmplitudeContextSpec.cpp +25 -0
  352. package/nitrogen/generated/shared/c++/HybridAmplitudeContextSpec.hpp +67 -0
  353. package/nitrogen/generated/shared/c++/HybridAmplitudeStorageSpec.cpp +30 -0
  354. package/nitrogen/generated/shared/c++/HybridAmplitudeStorageSpec.hpp +73 -0
  355. package/nitrogen/generated/shared/c++/HybridAmplitudeWorkerSpec.cpp +24 -0
  356. package/nitrogen/generated/shared/c++/HybridAmplitudeWorkerSpec.hpp +66 -0
  357. package/package.json +130 -0
  358. package/react-native-nitro-amplitude.podspec +36 -0
  359. package/src/AmplitudeContext.nitro.ts +21 -0
  360. package/src/AmplitudeStorage.nitro.ts +17 -0
  361. package/src/AmplitudeWorker.nitro.ts +25 -0
  362. package/src/analytics/campaign/campaign-tracker.ts +162 -0
  363. package/src/analytics/campaign/types.ts +18 -0
  364. package/src/analytics/config.ts +373 -0
  365. package/src/analytics/cookie-migration/index.ts +69 -0
  366. package/src/analytics/index.ts +36 -0
  367. package/src/analytics/migration/remnant-data-migration.ts +206 -0
  368. package/src/analytics/nitro-transport.ts +35 -0
  369. package/src/analytics/plugins/context.ts +166 -0
  370. package/src/analytics/react-native-client.ts +573 -0
  371. package/src/analytics/storage/local-storage.ts +76 -0
  372. package/src/analytics/types.ts +30 -0
  373. package/src/analytics/typings/browser-snippet.d.ts +7 -0
  374. package/src/analytics/typings/ua-parser.d.ts +4 -0
  375. package/src/analytics/utils/platform.ts +9 -0
  376. package/src/analytics/version.ts +1 -0
  377. package/src/experiment/experimentClient.ts +987 -0
  378. package/src/experiment/factory.ts +86 -0
  379. package/src/experiment/gen/version.ts +2 -0
  380. package/src/experiment/index.ts +14 -0
  381. package/src/experiment/integration/NativeExperimentReactNativeClient.ts +25 -0
  382. package/src/experiment/integration/connector.ts +82 -0
  383. package/src/experiment/integration/default.ts +107 -0
  384. package/src/experiment/logger/ampLogger.ts +76 -0
  385. package/src/experiment/logger/consoleLogger.ts +54 -0
  386. package/src/experiment/storage/cache.ts +271 -0
  387. package/src/experiment/storage/local-storage.ts +23 -0
  388. package/src/experiment/stubClient.ts +61 -0
  389. package/src/experiment/transport/http.ts +105 -0
  390. package/src/experiment/types/client.ts +38 -0
  391. package/src/experiment/types/config.ts +210 -0
  392. package/src/experiment/types/exposure.ts +107 -0
  393. package/src/experiment/types/logger.ts +71 -0
  394. package/src/experiment/types/source.ts +52 -0
  395. package/src/experiment/types/storage.ts +6 -0
  396. package/src/experiment/types/transport.ts +14 -0
  397. package/src/experiment/types/user.ts +132 -0
  398. package/src/experiment/types/variant.ts +36 -0
  399. package/src/experiment/util/backoff.ts +67 -0
  400. package/src/experiment/util/base64.ts +20 -0
  401. package/src/experiment/util/convert.ts +78 -0
  402. package/src/experiment/util/index.ts +23 -0
  403. package/src/experiment/util/platform.ts +9 -0
  404. package/src/experiment/util/randomstring.ts +12 -0
  405. package/src/experiment/util/userSessionExposureTracker.ts +47 -0
  406. package/src/index.ts +66 -0
  407. package/src/index.web.ts +19 -0
  408. package/src/native/context.ts +73 -0
  409. package/src/native/http.ts +77 -0
  410. package/src/native/hybrid.ts +32 -0
  411. package/src/native/storage.ts +107 -0
@@ -0,0 +1,107 @@
1
+ /**
2
+ * Event object for tracking exposures to Amplitude Experiment.
3
+ *
4
+ * This object contains all the required information to send an `$exposure`
5
+ * event through any SDK or CDP to experiment.
6
+ *
7
+ * The resulting exposure event must follow the following definition:
8
+ * ```
9
+ * {
10
+ * "event_type": "$exposure",
11
+ * "event_properties": {
12
+ * "flag_key": "<flagKey>",
13
+ * "variant": "<variant>",
14
+ * "experiment_key": "<expKey>"
15
+ * }
16
+ * }
17
+ * ```
18
+ *
19
+ * Where `<flagKey>`, `<variant>`, and `<expKey>` are the {@link flag_key},
20
+ * {@link variant}, and {@link experiment_key} variant members on this type:
21
+ *
22
+ * For example, if you're using Segment for analytics:
23
+ *
24
+ * ```
25
+ * analytics.track('$exposure', exposure)
26
+ * ```
27
+ */
28
+ export type Exposure = {
29
+ /**
30
+ * (Required) The key for the flag the user was exposed to.
31
+ */
32
+ flag_key: string;
33
+ /**
34
+ * (Optional) The variant the user was exposed to. If null or missing, the
35
+ * event will not be persisted, and will unset the user property.
36
+ */
37
+ variant?: string;
38
+ /**
39
+ * (Optional) The experiment key used to differentiate between multiple
40
+ * experiments associated with the same flag.
41
+ */
42
+ experiment_key?: string;
43
+ /**
44
+ * (Optional) Flag, segment, and variant metadata produced as a result of
45
+ * evaluation for the user. Used for system purposes.
46
+ */
47
+ metadata?: Record<string, unknown>;
48
+ };
49
+
50
+ /**
51
+ * Interface for enabling tracking {@link Exposure}s through the
52
+ * {@link ExperimentClient}.
53
+ *
54
+ * If you're using the Amplitude Analytics SDK for tracking you do not need
55
+ * to implement this interface. Simply initialize experiment using the
56
+ * {@link Experiment.initializeWithAmplitudeAnalytics} function.
57
+ *
58
+ * If you're using a 3rd party analytics implementation then you'll need to
59
+ * implement the sending of the analytics event yourself. The implementation
60
+ * should result in the following event getting sent to amplitude:
61
+ *
62
+ * ```
63
+ * {
64
+ * "event_type": "$exposure",
65
+ * "event_properties": {
66
+ * "flag_key": "<flagKey>",
67
+ * "variant": "<variant>",
68
+ * "experiment_key": "<expKey>"
69
+ * }
70
+ * }
71
+ * ```
72
+ *
73
+ * For example, if you're using Segment for analytics:
74
+ *
75
+ * ```
76
+ * analytics.track('$exposure', exposure)
77
+ * ```
78
+ */
79
+ export interface ExposureTrackingProvider {
80
+ /**
81
+ * Called when the {@link ExperimentClient} intends to track an exposure event;
82
+ * either when {@link ExperimentClient.variant} serves a variant (and
83
+ * {@link ExperimentConfig.automaticExposureTracking} is `true`) or if
84
+ * {@link ExperimentClient.exposure} is called.
85
+ *
86
+ * The implementation should result in the following event getting sent to
87
+ * amplitude:
88
+ *
89
+ * ```
90
+ * {
91
+ * "event_type": "$exposure",
92
+ * "event_properties": {
93
+ * "flag_key": "<flagKey>",
94
+ * "variant": "<variant>",
95
+ * "experiment_key": "<expKey>"
96
+ * }
97
+ * }
98
+ * ```
99
+ *
100
+ * For example, if you're using Segment for analytics:
101
+ *
102
+ * ```
103
+ * analytics.track('$exposure', exposure)
104
+ * ```
105
+ */
106
+ track(exposure: Exposure): void;
107
+ }
@@ -0,0 +1,71 @@
1
+ /**
2
+ * Log level enumeration for controlling logging verbosity.
3
+ * @category Logging
4
+ */
5
+ export enum LogLevel {
6
+ /**
7
+ * Disable all logging
8
+ */
9
+ Disable = 0,
10
+ /**
11
+ * Error level logging - only critical errors
12
+ */
13
+ Error = 1,
14
+ /**
15
+ * Warning level logging - errors and warnings
16
+ */
17
+ Warn = 2,
18
+ /**
19
+ * Info level logging - errors, warnings, and informational messages
20
+ */
21
+ Info = 3,
22
+ /**
23
+ * Debug level logging - errors, warnings, info, and debug messages
24
+ */
25
+ Debug = 4,
26
+ /**
27
+ * Verbose level logging - all messages including verbose details
28
+ */
29
+ Verbose = 5,
30
+ }
31
+
32
+ /**
33
+ * Logger interface that can be implemented to provide custom logging.
34
+ * @category Logging
35
+ */
36
+ export interface Logger {
37
+ /**
38
+ * Log an error message
39
+ * @param message The message to log
40
+ * @param optionalParams Additional parameters to log
41
+ */
42
+ error(message?: any, ...optionalParams: any[]): void;
43
+
44
+ /**
45
+ * Log a warning message
46
+ * @param message The message to log
47
+ * @param optionalParams Additional parameters to log
48
+ */
49
+ warn(message?: any, ...optionalParams: any[]): void;
50
+
51
+ /**
52
+ * Log an informational message
53
+ * @param message The message to log
54
+ * @param optionalParams Additional parameters to log
55
+ */
56
+ info(message?: any, ...optionalParams: any[]): void;
57
+
58
+ /**
59
+ * Log a debug message
60
+ * @param message The message to log
61
+ * @param optionalParams Additional parameters to log
62
+ */
63
+ debug(message?: any, ...optionalParams: any[]): void;
64
+
65
+ /**
66
+ * Log a verbose message
67
+ * @param message The message to log
68
+ * @param optionalParams Additional parameters to log
69
+ */
70
+ verbose(message?: any, ...optionalParams: any[]): void;
71
+ }
@@ -0,0 +1,52 @@
1
+ /**
2
+ * Determines the primary source of variants before falling back.
3
+ *
4
+ * @category Source
5
+ */
6
+ export enum Source {
7
+ /**
8
+ * The default way to source variants within your application. Before the
9
+ * assignments are fetched, `getVariant(s)` will fallback to local storage
10
+ * first, then `initialVariants` if local storage is empty. This option
11
+ * effectively falls back to an assignment fetched previously.
12
+ */
13
+ LocalStorage = "localStorage",
14
+
15
+ /**
16
+ * This bootstrap option is used primarily for servers-side rendering using an
17
+ * Experiment server SDK. This bootstrap option always prefers the config
18
+ * `initialVariants` over data in local storage, even if variants are fetched
19
+ * successfully and stored locally.
20
+ */
21
+ InitialVariants = "initialVariants",
22
+ }
23
+
24
+ /**
25
+ * Indicates from which source the variant() function determines the variant
26
+ *
27
+ * @category Source
28
+ */
29
+ export enum VariantSource {
30
+ LocalStorage = "storage",
31
+ InitialVariants = "initial",
32
+ SecondaryLocalStorage = "secondary-storage",
33
+ SecondaryInitialVariants = "secondary-initial",
34
+ FallbackInline = "fallback-inline",
35
+ FallbackConfig = "fallback-config",
36
+ LocalEvaluation = "local-evaluation",
37
+ }
38
+
39
+ /**
40
+ * Returns true if the VariantSource is one of the fallbacks (inline or config)
41
+ *
42
+ * @param source a {@link VariantSource}
43
+ * @returns true if source is {@link VariantSource.FallbackInline} or {@link VariantSource.FallbackConfig}
44
+ */
45
+ export const isFallback = (source: VariantSource | undefined): boolean => {
46
+ return (
47
+ !source ||
48
+ source === VariantSource.FallbackInline ||
49
+ source === VariantSource.FallbackConfig ||
50
+ source === VariantSource.SecondaryInitialVariants
51
+ );
52
+ };
@@ -0,0 +1,6 @@
1
+ export interface Storage {
2
+ get(key: string): Promise<string | null>;
3
+ put(key: string, value: string): Promise<void>;
4
+ delete(key: string): Promise<void>;
5
+ reset?(): Promise<void>;
6
+ }
@@ -0,0 +1,14 @@
1
+ export interface SimpleResponse {
2
+ status: number;
3
+ body: string;
4
+ }
5
+
6
+ export interface HttpClient {
7
+ request(
8
+ requestUrl: string,
9
+ method: string,
10
+ headers: Record<string, string>,
11
+ data: string | null,
12
+ timeoutMillis?: number,
13
+ ): Promise<SimpleResponse>;
14
+ }
@@ -0,0 +1,132 @@
1
+ /**
2
+ * Defines a user context for evaluation.
3
+ * `device_id` and `user_id` are used for identity resolution.
4
+ * All other predefined fields and user properties are used for
5
+ * rule based user targeting.
6
+ * @category Types
7
+ */
8
+ export type ExperimentUser = {
9
+ /**
10
+ * Device ID for associating with an identity in Amplitude
11
+ */
12
+ device_id?: string;
13
+
14
+ /**
15
+ * User ID for associating with an identity in Amplitude
16
+ */
17
+ user_id?: string;
18
+
19
+ /**
20
+ * Predefined field, can be manually provided
21
+ */
22
+ country?: string;
23
+
24
+ /**
25
+ * Predefined field, can be manually provided
26
+ */
27
+ city?: string;
28
+
29
+ /**
30
+ * Predefined field, can be manually provided
31
+ */
32
+ region?: string;
33
+
34
+ /**
35
+ * Predefined field, can be manually provided
36
+ */
37
+ dma?: string;
38
+
39
+ /**
40
+ * Predefined field, auto populated via a ExperimentUserProvider
41
+ * or can be manually provided
42
+ */
43
+ language?: string;
44
+
45
+ /**
46
+ * Predefined field, auto populated via a ExperimentUserProvider
47
+ * or can be manually provided
48
+ */
49
+ platform?: string;
50
+
51
+ /**
52
+ * Predefined field, auto populated via a ExperimentUserProvider
53
+ * or can be manually provided
54
+ */
55
+ version?: string;
56
+
57
+ /**
58
+ * Predefined field, auto populated via a ExperimentUserProvider
59
+ * or can be manually provided
60
+ */
61
+ os?: string;
62
+
63
+ /**
64
+ * Predefined field, auto populated via a ExperimentUserProvider
65
+ * or can be manually provided
66
+ */
67
+ device_model?: string;
68
+
69
+ /**
70
+ * Predefined field, auto populated via a ExperimentUserProvider
71
+ * or can be manually provided
72
+ */
73
+ device_brand?: string;
74
+
75
+ /**
76
+ * Predefined field, auto populated via a ExperimentUserProvider
77
+ * or can be manually provided
78
+ */
79
+ device_manufacturer?: string;
80
+
81
+ /**
82
+ * Predefined field, can be manually provided
83
+ */
84
+ carrier?: string;
85
+
86
+ /**
87
+ * Predefined field, auto populated, can be manually overridden
88
+ */
89
+ library?: string;
90
+
91
+ /**
92
+ * Predefined field, can be manually provided
93
+ */
94
+ ip_address?: string;
95
+
96
+ /**
97
+ * Custom user properties
98
+ */
99
+ user_properties?: {
100
+ [propertyName: string]:
101
+ | string
102
+ | number
103
+ | boolean
104
+ | (string | number | boolean)[];
105
+ };
106
+
107
+ groups?: {
108
+ [groupType: string]: string[];
109
+ };
110
+
111
+ group_properties?: {
112
+ [groupType: string]: {
113
+ [groupName: string]: {
114
+ [propertyName: string]:
115
+ | string
116
+ | number
117
+ | boolean
118
+ | (string | number | boolean)[];
119
+ };
120
+ };
121
+ };
122
+ };
123
+
124
+ /**
125
+ * An ExperimentUserProvider injects information into the {@link ExperimentUser}
126
+ * object before sending a request to the server. This can be used to pass
127
+ * identity (deviceId and userId), or other platform specific context.
128
+ * @category Provider
129
+ */
130
+ export interface ExperimentUserProvider {
131
+ getUser(): Promise<ExperimentUser>;
132
+ }
@@ -0,0 +1,36 @@
1
+ /**
2
+ * @category Types
3
+ */
4
+ export type Variant = {
5
+ /**
6
+ * The key of the variant.
7
+ */
8
+ key?: string;
9
+ /**
10
+ * The value of the variant.
11
+ */
12
+ value?: string;
13
+
14
+ /**
15
+ * The attached payload, if any.
16
+ */
17
+ payload?: any;
18
+
19
+ /**
20
+ * The experiment key. Used to distinguish two experiments associated with the same flag.
21
+ */
22
+ expKey?: string;
23
+
24
+ /**
25
+ * Flag, segment, and variant metadata produced as a result of
26
+ * evaluation for the user. Used for system purposes.
27
+ */
28
+ metadata?: Record<string, unknown>;
29
+ };
30
+
31
+ /**
32
+ * @category Types
33
+ */
34
+ export type Variants = {
35
+ [key: string]: Variant;
36
+ };
@@ -0,0 +1,67 @@
1
+ import { safeGlobal } from "@amplitude/experiment-core";
2
+
3
+ export class Backoff {
4
+ private readonly attempts: number;
5
+ private readonly min: number;
6
+ private readonly max: number;
7
+ private readonly scalar: number;
8
+
9
+ private started = false;
10
+ private done = false;
11
+
12
+ private timeoutHandle: ReturnType<typeof safeGlobal.setTimeout> | undefined;
13
+
14
+ public constructor(
15
+ attempts: number,
16
+ min: number,
17
+ max: number,
18
+ scalar: number,
19
+ ) {
20
+ this.attempts = attempts;
21
+ this.min = min;
22
+ this.max = max;
23
+ this.scalar = scalar;
24
+ }
25
+
26
+ public start(fn: () => Promise<void>): void {
27
+ if (!this.started) {
28
+ this.started = true;
29
+ } else {
30
+ throw Error("Backoff already started");
31
+ }
32
+ this.backoff(fn, 0, this.min);
33
+ }
34
+
35
+ public cancel(): void {
36
+ this.done = true;
37
+ if (this.timeoutHandle != null) {
38
+ safeGlobal.clearTimeout(this.timeoutHandle);
39
+ this.timeoutHandle = undefined;
40
+ }
41
+ }
42
+
43
+ private backoff(
44
+ fn: () => Promise<void>,
45
+ attempt: number,
46
+ delay: number,
47
+ ): void {
48
+ if (this.done) {
49
+ return;
50
+ }
51
+ this.timeoutHandle = safeGlobal.setTimeout(async () => {
52
+ try {
53
+ this.timeoutHandle = undefined;
54
+ await fn();
55
+ this.done = true;
56
+ } catch (e) {
57
+ const nextAttempt = attempt + 1;
58
+ if (!this.done && nextAttempt < this.attempts) {
59
+ const nextDelay = Math.min(delay * this.scalar, this.max);
60
+ this.backoff(fn, nextAttempt, nextDelay);
61
+ } else {
62
+ this.done = true;
63
+ }
64
+ }
65
+ }, delay);
66
+ }
67
+ }
@@ -0,0 +1,20 @@
1
+ import * as base64 from "base64-js";
2
+
3
+ export const stringToUtf8Array = (s: string): number[] => {
4
+ const utf8 = unescape(encodeURIComponent(s));
5
+ const arr = [];
6
+ for (let i = 0; i < utf8.length; i++) {
7
+ arr.push(utf8.charCodeAt(i));
8
+ }
9
+ return arr;
10
+ };
11
+
12
+ export const urlSafeBase64Encode = (s: string): string => {
13
+ const base64encoded = base64.fromByteArray(
14
+ new Uint8Array(stringToUtf8Array(s)),
15
+ );
16
+ return base64encoded
17
+ .replace(/[=]/g, "")
18
+ .replace(/\+/g, "-")
19
+ .replace(/\//g, "_");
20
+ };
@@ -0,0 +1,78 @@
1
+ import { EvaluationVariant } from "@amplitude/experiment-core";
2
+
3
+ import { ExperimentUser } from "../types/user";
4
+ import { Variant } from "../types/variant";
5
+
6
+ export const convertUserToContext = (
7
+ user: ExperimentUser | undefined,
8
+ ): Record<string, unknown> => {
9
+ if (!user) {
10
+ return {};
11
+ }
12
+ const contextUser: ExperimentUser = { ...user };
13
+ const context: Record<string, unknown> = { user: contextUser };
14
+ const groups: Record<string, Record<string, unknown>> = {};
15
+ if (!user.groups) {
16
+ return context;
17
+ }
18
+ for (const groupType of Object.keys(user.groups)) {
19
+ const groupNames: string[] = user.groups[groupType] ?? [];
20
+ if (groupNames.length > 0 && groupNames[0]) {
21
+ const groupName = groupNames[0];
22
+ const groupNameMap: Record<string, unknown> = {
23
+ group_name: groupName,
24
+ };
25
+ // Check for group properties
26
+ const groupProperties = user.group_properties?.[groupType]?.[groupName];
27
+ if (groupProperties && Object.keys(groupProperties).length > 0) {
28
+ groupNameMap["group_properties"] = groupProperties;
29
+ }
30
+ groups[groupType] = groupNameMap;
31
+ }
32
+ }
33
+ if (Object.keys(groups).length > 0) {
34
+ context["groups"] = groups;
35
+ }
36
+ delete contextUser.groups;
37
+ delete contextUser.group_properties;
38
+ return context;
39
+ };
40
+
41
+ export const convertVariant = (
42
+ value: string | Variant | undefined,
43
+ ): Variant => {
44
+ if (value === null || value === undefined) {
45
+ return {};
46
+ }
47
+ if (typeof value === "string") {
48
+ return {
49
+ key: value,
50
+ value: value,
51
+ };
52
+ } else {
53
+ return value;
54
+ }
55
+ };
56
+
57
+ export const convertEvaluationVariantToVariant = (
58
+ evaluationVariant: EvaluationVariant,
59
+ ): Variant => {
60
+ if (!evaluationVariant) {
61
+ return {};
62
+ }
63
+ let experimentKey: string | undefined;
64
+ if (evaluationVariant.metadata) {
65
+ const metadataExperimentKey = evaluationVariant.metadata["experimentKey"];
66
+ if (typeof metadataExperimentKey === "string") {
67
+ experimentKey = metadataExperimentKey;
68
+ }
69
+ }
70
+ const variant: Variant = {};
71
+ if (evaluationVariant.key) variant.key = evaluationVariant.key;
72
+ if (evaluationVariant.value)
73
+ variant.value = evaluationVariant.value as string;
74
+ if (evaluationVariant.payload) variant.payload = evaluationVariant.payload;
75
+ if (experimentKey) variant.expKey = experimentKey;
76
+ if (evaluationVariant.metadata) variant.metadata = evaluationVariant.metadata;
77
+ return variant;
78
+ };
@@ -0,0 +1,23 @@
1
+ import { EvaluationFlag } from "@amplitude/experiment-core";
2
+
3
+ export const isNullOrUndefined = (value: unknown): boolean => {
4
+ return value === null || value === undefined;
5
+ };
6
+
7
+ export const isNullUndefinedOrEmpty = (value: unknown): boolean => {
8
+ if (isNullOrUndefined(value)) return true;
9
+ if (value === null || typeof value !== "object") return false;
10
+ return Object.keys(value).length === 0;
11
+ };
12
+
13
+ export const isLocalEvaluationMode = (
14
+ flag: EvaluationFlag | undefined,
15
+ ): boolean => {
16
+ return flag?.metadata?.evaluationMode === "local";
17
+ };
18
+
19
+ export const isRemoteEvaluationMode = (
20
+ flag: EvaluationFlag | undefined,
21
+ ): boolean => {
22
+ return flag?.metadata?.evaluationMode === "remote";
23
+ };
@@ -0,0 +1,9 @@
1
+ import { Platform } from "react-native";
2
+
3
+ export const isWeb = (): boolean => {
4
+ return Platform.OS === "web";
5
+ };
6
+
7
+ export const isNative = (): boolean => {
8
+ return !isWeb();
9
+ };
@@ -0,0 +1,12 @@
1
+ const CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
2
+
3
+ export const randomString = (
4
+ length: number,
5
+ alphabet: string = CHARS,
6
+ ): string => {
7
+ let str = "";
8
+ for (let i = 0; i < length; ++i) {
9
+ str += alphabet.charAt(Math.floor(Math.random() * alphabet.length));
10
+ }
11
+ return str;
12
+ };
@@ -0,0 +1,47 @@
1
+ import { Exposure, ExposureTrackingProvider } from "../types/exposure";
2
+ import { ExperimentUser } from "../types/user";
3
+
4
+ interface Identity {
5
+ userId?: string;
6
+ deviceId?: string;
7
+ }
8
+
9
+ /**
10
+ * A wrapper for an exposure tracking provider which only sends one exposure event per
11
+ * flag, per variant, per user session. When the user identity (userId or deviceId) changes,
12
+ * the tracking cache is reset to ensure exposures are tracked for the new user session.
13
+ */
14
+ export class UserSessionExposureTracker {
15
+ private readonly exposureTrackingProvider: ExposureTrackingProvider;
16
+ private tracked: Record<string, string | undefined> = {};
17
+ private identity: Identity = {};
18
+
19
+ constructor(exposureTrackingProvider: ExposureTrackingProvider) {
20
+ this.exposureTrackingProvider = exposureTrackingProvider;
21
+ }
22
+
23
+ track(exposure: Exposure, user?: ExperimentUser): void {
24
+ const newIdentity: Identity = {
25
+ userId: user?.user_id,
26
+ deviceId: user?.device_id,
27
+ };
28
+
29
+ if (!this.identityEquals(this.identity, newIdentity)) {
30
+ this.tracked = {};
31
+ }
32
+ this.identity = newIdentity;
33
+
34
+ const hasTrackedFlag = exposure.flag_key in this.tracked;
35
+ const trackedVariant = this.tracked[exposure.flag_key];
36
+ if (hasTrackedFlag && trackedVariant === exposure.variant) {
37
+ return;
38
+ }
39
+
40
+ this.tracked[exposure.flag_key] = exposure.variant;
41
+ this.exposureTrackingProvider.track(exposure);
42
+ }
43
+
44
+ private identityEquals(id1: Identity, id2: Identity): boolean {
45
+ return id1.userId === id2.userId && id1.deviceId === id2.deviceId;
46
+ }
47
+ }