@billdog.io/react-native 1.0.0-beta.2

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 (309) hide show
  1. package/BillDogReactNative.podspec +30 -0
  2. package/LICENSE +21 -0
  3. package/README.md +330 -0
  4. package/android/build.gradle +99 -0
  5. package/android/src/main/AndroidManifest.xml +1 -0
  6. package/android/src/main/kotlin/io/billdog/reactnative/BillDogABTestModule.kt +317 -0
  7. package/android/src/main/kotlin/io/billdog/reactnative/BillDogAnalyticsModule.kt +389 -0
  8. package/android/src/main/kotlin/io/billdog/reactnative/BillDogModule.kt +817 -0
  9. package/android/src/main/kotlin/io/billdog/reactnative/BillDogPaywallViewManager.kt +383 -0
  10. package/android/src/main/kotlin/io/billdog/reactnative/BillDogSurveyModule.kt +427 -0
  11. package/android/src/main/kotlin/io/billdog/reactnative/BillDogVirtualCurrencyModule.kt +407 -0
  12. package/android/src/main/kotlin/io/billdog/virtualcurrency/BillDogVirtualCurrencyPackage.kt +44 -0
  13. package/dist/AdvancedPaywallCache.d.ts +70 -0
  14. package/dist/AdvancedPaywallCache.js +344 -0
  15. package/dist/BillDog.d.ts +255 -0
  16. package/dist/BillDog.js +918 -0
  17. package/dist/BillDogConfiguration.d.ts +145 -0
  18. package/dist/BillDogConfiguration.js +229 -0
  19. package/dist/ComponentRenderer.d.ts +17 -0
  20. package/dist/ComponentRenderer.js +886 -0
  21. package/dist/LayoutEngine.d.ts +101 -0
  22. package/dist/LayoutEngine.js +394 -0
  23. package/dist/LocalizationResolver.d.ts +99 -0
  24. package/dist/LocalizationResolver.js +266 -0
  25. package/dist/NativePaywallView.d.ts +36 -0
  26. package/dist/NativePaywallView.js +59 -0
  27. package/dist/PaywallCache.d.ts +74 -0
  28. package/dist/PaywallCache.js +293 -0
  29. package/dist/PaywallStateManager.d.ts +62 -0
  30. package/dist/PaywallStateManager.js +147 -0
  31. package/dist/PaywallView.d.ts +42 -0
  32. package/dist/PaywallView.js +275 -0
  33. package/dist/ProductVariableProvider.d.ts +60 -0
  34. package/dist/ProductVariableProvider.js +239 -0
  35. package/dist/VariableResolver.d.ts +120 -0
  36. package/dist/VariableResolver.js +379 -0
  37. package/dist/WebViewPaywall.d.ts +75 -0
  38. package/dist/WebViewPaywall.js +360 -0
  39. package/dist/animations/presets.d.ts +49 -0
  40. package/dist/animations/presets.js +367 -0
  41. package/dist/components/AccoladeCpsComponent.d.ts +13 -0
  42. package/dist/components/AccoladeCpsComponent.js +248 -0
  43. package/dist/components/AccordionComponent.d.ts +10 -0
  44. package/dist/components/AccordionComponent.js +187 -0
  45. package/dist/components/AnimatedWrapper.d.ts +35 -0
  46. package/dist/components/AnimatedWrapper.js +277 -0
  47. package/dist/components/CarouselComponent.d.ts +23 -0
  48. package/dist/components/CarouselComponent.js +484 -0
  49. package/dist/components/ChartCurveComponent.d.ts +13 -0
  50. package/dist/components/ChartCurveComponent.js +333 -0
  51. package/dist/components/CheckboxComponent.d.ts +9 -0
  52. package/dist/components/CheckboxComponent.js +172 -0
  53. package/dist/components/ConfettiComponent.d.ts +9 -0
  54. package/dist/components/ConfettiComponent.js +172 -0
  55. package/dist/components/CountdownComponent.d.ts +16 -0
  56. package/dist/components/CountdownComponent.js +414 -0
  57. package/dist/components/DelayedXComponent.d.ts +12 -0
  58. package/dist/components/DelayedXComponent.js +240 -0
  59. package/dist/components/DrawerModalComponent.d.ts +20 -0
  60. package/dist/components/DrawerModalComponent.js +286 -0
  61. package/dist/components/GradientView.d.ts +38 -0
  62. package/dist/components/GradientView.js +126 -0
  63. package/dist/components/HapticFeedbackComponent.d.ts +16 -0
  64. package/dist/components/HapticFeedbackComponent.js +64 -0
  65. package/dist/components/HorizontalProductsComponent.d.ts +17 -0
  66. package/dist/components/HorizontalProductsComponent.js +284 -0
  67. package/dist/components/MultiChoiceGridComponent.d.ts +13 -0
  68. package/dist/components/MultiChoiceGridComponent.js +234 -0
  69. package/dist/components/NPSScaleComponent.d.ts +16 -0
  70. package/dist/components/NPSScaleComponent.js +260 -0
  71. package/dist/components/NavigationComponent.d.ts +26 -0
  72. package/dist/components/NavigationComponent.js +302 -0
  73. package/dist/components/OAuthButtonComponent.d.ts +20 -0
  74. package/dist/components/OAuthButtonComponent.js +237 -0
  75. package/dist/components/ProgressLoaderComponent.d.ts +13 -0
  76. package/dist/components/ProgressLoaderComponent.js +308 -0
  77. package/dist/components/ProgressStepperComponent.d.ts +18 -0
  78. package/dist/components/ProgressStepperComponent.js +228 -0
  79. package/dist/components/SegmentedPickerComponent.d.ts +10 -0
  80. package/dist/components/SegmentedPickerComponent.js +221 -0
  81. package/dist/components/ShareButtonsComponent.d.ts +21 -0
  82. package/dist/components/ShareButtonsComponent.js +265 -0
  83. package/dist/components/ShareCodeComponent.d.ts +16 -0
  84. package/dist/components/ShareCodeComponent.js +274 -0
  85. package/dist/components/SingleChoiceGridComponent.d.ts +13 -0
  86. package/dist/components/SingleChoiceGridComponent.js +210 -0
  87. package/dist/components/SliderComponent.d.ts +9 -0
  88. package/dist/components/SliderComponent.js +263 -0
  89. package/dist/components/StarRatingInputComponent.d.ts +20 -0
  90. package/dist/components/StarRatingInputComponent.js +198 -0
  91. package/dist/components/StickerCompositeComponent.d.ts +13 -0
  92. package/dist/components/StickerCompositeComponent.js +136 -0
  93. package/dist/components/TabsComponent.d.ts +19 -0
  94. package/dist/components/TabsComponent.js +431 -0
  95. package/dist/components/TextInputComponent.d.ts +18 -0
  96. package/dist/components/TextInputComponent.js +227 -0
  97. package/dist/components/TimelineComponent.d.ts +19 -0
  98. package/dist/components/TimelineComponent.js +104 -0
  99. package/dist/components/ToggleComponent.d.ts +14 -0
  100. package/dist/components/ToggleComponent.js +132 -0
  101. package/dist/components/VerticalProductsComponent.d.ts +17 -0
  102. package/dist/components/VerticalProductsComponent.js +311 -0
  103. package/dist/dynamicValues.d.ts +36 -0
  104. package/dist/dynamicValues.js +142 -0
  105. package/dist/filters/dateFilters.d.ts +50 -0
  106. package/dist/filters/dateFilters.js +390 -0
  107. package/dist/filters/index.d.ts +18 -0
  108. package/dist/filters/index.js +253 -0
  109. package/dist/hooks/useOfferings.d.ts +76 -0
  110. package/dist/hooks/useOfferings.js +99 -0
  111. package/dist/hooks/usePaywall.d.ts +27 -0
  112. package/dist/hooks/usePaywall.js +114 -0
  113. package/dist/hooks/usePlacement.d.ts +34 -0
  114. package/dist/hooks/usePlacement.js +89 -0
  115. package/dist/hooks/useSubscription.d.ts +40 -0
  116. package/dist/hooks/useSubscription.js +97 -0
  117. package/dist/index.d.ts +98 -0
  118. package/dist/index.js +198 -0
  119. package/dist/models/BillDogError.d.ts +40 -0
  120. package/dist/models/BillDogError.js +11 -0
  121. package/dist/models/CacheFetchPolicy.d.ts +8 -0
  122. package/dist/models/CacheFetchPolicy.js +4 -0
  123. package/dist/models/CustomProduct.d.ts +32 -0
  124. package/dist/models/CustomProduct.js +15 -0
  125. package/dist/models/CustomerInfo.d.ts +17 -0
  126. package/dist/models/CustomerInfo.js +11 -0
  127. package/dist/models/Delegate.d.ts +20 -0
  128. package/dist/models/Delegate.js +11 -0
  129. package/dist/models/EntitlementInfo.d.ts +19 -0
  130. package/dist/models/EntitlementInfo.js +2 -0
  131. package/dist/models/Placement.d.ts +54 -0
  132. package/dist/models/Placement.js +15 -0
  133. package/dist/models/PurchaseParams.d.ts +39 -0
  134. package/dist/models/PurchaseParams.js +60 -0
  135. package/dist/models/PurchaseResult.d.ts +30 -0
  136. package/dist/models/PurchaseResult.js +15 -0
  137. package/dist/models/RestoreResult.d.ts +30 -0
  138. package/dist/models/RestoreResult.js +22 -0
  139. package/dist/models/RestoredItem.d.ts +26 -0
  140. package/dist/models/RestoredItem.js +13 -0
  141. package/dist/modules/ABTest.d.ts +65 -0
  142. package/dist/modules/ABTest.js +113 -0
  143. package/dist/modules/Analytics.d.ts +91 -0
  144. package/dist/modules/Analytics.js +182 -0
  145. package/dist/modules/Survey.d.ts +65 -0
  146. package/dist/modules/Survey.js +82 -0
  147. package/dist/modules/VirtualCurrency.d.ts +63 -0
  148. package/dist/modules/VirtualCurrency.js +147 -0
  149. package/dist/murmur.d.ts +23 -0
  150. package/dist/murmur.js +104 -0
  151. package/dist/notifications/LiveActivitiesManager.d.ts +47 -0
  152. package/dist/notifications/LiveActivitiesManager.js +106 -0
  153. package/dist/notifications/NotificationScheduler.d.ts +55 -0
  154. package/dist/notifications/NotificationScheduler.js +199 -0
  155. package/dist/notifications/PurchaseNotificationHandler.d.ts +24 -0
  156. package/dist/notifications/PurchaseNotificationHandler.js +55 -0
  157. package/dist/notifications/useDeviceToken.d.ts +36 -0
  158. package/dist/notifications/useDeviceToken.js +97 -0
  159. package/dist/notifications/useLiveActivity.d.ts +39 -0
  160. package/dist/notifications/useLiveActivity.js +104 -0
  161. package/dist/review/ReviewAnalytics.d.ts +34 -0
  162. package/dist/review/ReviewAnalytics.js +73 -0
  163. package/dist/review/ReviewManager.d.ts +83 -0
  164. package/dist/review/ReviewManager.js +339 -0
  165. package/dist/review/ReviewTimingManager.d.ts +82 -0
  166. package/dist/review/ReviewTimingManager.js +224 -0
  167. package/dist/survey-core/types.d.ts +215 -0
  168. package/dist/survey-core/types.js +8 -0
  169. package/dist/types.d.ts +438 -0
  170. package/dist/types.js +158 -0
  171. package/dist/utils/ApiClient.d.ts +65 -0
  172. package/dist/utils/ApiClient.js +132 -0
  173. package/dist/utils/CSSConverter.d.ts +49 -0
  174. package/dist/utils/CSSConverter.js +470 -0
  175. package/dist/utils/animations.d.ts +41 -0
  176. package/dist/utils/animations.js +194 -0
  177. package/dist/utils/calendarIntegration.d.ts +36 -0
  178. package/dist/utils/calendarIntegration.js +89 -0
  179. package/dist/utils/configurationResolver.d.ts +23 -0
  180. package/dist/utils/configurationResolver.js +78 -0
  181. package/dist/utils/deviceDetection.d.ts +38 -0
  182. package/dist/utils/deviceDetection.js +59 -0
  183. package/dist/utils/hapticFeedback.d.ts +17 -0
  184. package/dist/utils/hapticFeedback.js +53 -0
  185. package/dist/utils/iconMapper.d.ts +26 -0
  186. package/dist/utils/iconMapper.js +113 -0
  187. package/dist/utils/notificationPermissions.d.ts +13 -0
  188. package/dist/utils/notificationPermissions.js +51 -0
  189. package/dist/utils/priceFormatting.d.ts +19 -0
  190. package/dist/utils/priceFormatting.js +99 -0
  191. package/dist/utils/shareSheet.d.ts +17 -0
  192. package/dist/utils/shareSheet.js +42 -0
  193. package/dist/utils/subscriptionUpgrade.d.ts +84 -0
  194. package/dist/utils/subscriptionUpgrade.js +100 -0
  195. package/dist/valueUtils.d.ts +48 -0
  196. package/dist/valueUtils.js +129 -0
  197. package/dist/xFlowTags.d.ts +18 -0
  198. package/dist/xFlowTags.js +385 -0
  199. package/ios/BillDogABTest.m +50 -0
  200. package/ios/BillDogABTest.swift +188 -0
  201. package/ios/BillDogAnalytics.m +105 -0
  202. package/ios/BillDogAnalytics.swift +324 -0
  203. package/ios/BillDogBridge.m +222 -0
  204. package/ios/BillDogBridge.swift +715 -0
  205. package/ios/BillDogLiveActivities.m +41 -0
  206. package/ios/BillDogLiveActivities.swift +104 -0
  207. package/ios/BillDogPaywallViewManager.m +39 -0
  208. package/ios/BillDogPaywallViewManager.swift +361 -0
  209. package/ios/BillDogSurvey.m +34 -0
  210. package/ios/BillDogSurvey.swift +257 -0
  211. package/ios/BillDogVirtualCurrencyBridge.m +63 -0
  212. package/ios/BillDogVirtualCurrencyBridge.swift +511 -0
  213. package/junit.xml +25 -0
  214. package/package.json +61 -0
  215. package/react-native.config.js +13 -0
  216. package/src/AdvancedPaywallCache.ts +433 -0
  217. package/src/BillDog.ts +983 -0
  218. package/src/BillDogConfiguration.ts +318 -0
  219. package/src/ComponentRenderer.tsx +1325 -0
  220. package/src/LayoutEngine.ts +459 -0
  221. package/src/LocalizationResolver.ts +311 -0
  222. package/src/NativePaywallView.tsx +132 -0
  223. package/src/PaywallCache.ts +358 -0
  224. package/src/PaywallStateManager.ts +154 -0
  225. package/src/PaywallView.tsx +328 -0
  226. package/src/ProductVariableProvider.ts +282 -0
  227. package/src/VariableResolver.ts +516 -0
  228. package/src/WebViewPaywall.tsx +454 -0
  229. package/src/animations/presets.ts +421 -0
  230. package/src/components/AccoladeCpsComponent.tsx +259 -0
  231. package/src/components/AccordionComponent.tsx +213 -0
  232. package/src/components/AnimatedWrapper.tsx +316 -0
  233. package/src/components/CarouselComponent.tsx +615 -0
  234. package/src/components/ChartCurveComponent.tsx +452 -0
  235. package/src/components/CheckboxComponent.tsx +185 -0
  236. package/src/components/ConfettiComponent.tsx +178 -0
  237. package/src/components/CountdownComponent.tsx +454 -0
  238. package/src/components/DelayedXComponent.tsx +266 -0
  239. package/src/components/DrawerModalComponent.tsx +324 -0
  240. package/src/components/GradientView.tsx +129 -0
  241. package/src/components/HapticFeedbackComponent.tsx +39 -0
  242. package/src/components/HorizontalProductsComponent.tsx +329 -0
  243. package/src/components/MultiChoiceGridComponent.tsx +265 -0
  244. package/src/components/NPSScaleComponent.tsx +294 -0
  245. package/src/components/NavigationComponent.tsx +329 -0
  246. package/src/components/OAuthButtonComponent.tsx +266 -0
  247. package/src/components/ProgressLoaderComponent.tsx +366 -0
  248. package/src/components/ProgressStepperComponent.tsx +250 -0
  249. package/src/components/SegmentedPickerComponent.tsx +245 -0
  250. package/src/components/ShareButtonsComponent.tsx +299 -0
  251. package/src/components/ShareCodeComponent.tsx +303 -0
  252. package/src/components/SingleChoiceGridComponent.tsx +229 -0
  253. package/src/components/SliderComponent.tsx +280 -0
  254. package/src/components/StarRatingInputComponent.tsx +223 -0
  255. package/src/components/StickerCompositeComponent.tsx +168 -0
  256. package/src/components/TabsComponent.tsx +496 -0
  257. package/src/components/TextInputComponent.tsx +258 -0
  258. package/src/components/TimelineComponent.tsx +129 -0
  259. package/src/components/ToggleComponent.tsx +142 -0
  260. package/src/components/VerticalProductsComponent.tsx +357 -0
  261. package/src/dynamicValues.ts +180 -0
  262. package/src/filters/dateFilters.ts +411 -0
  263. package/src/filters/index.ts +281 -0
  264. package/src/hooks/useOfferings.ts +192 -0
  265. package/src/hooks/usePaywall.ts +154 -0
  266. package/src/hooks/usePlacement.ts +143 -0
  267. package/src/hooks/useSubscription.ts +154 -0
  268. package/src/index.ts +245 -0
  269. package/src/models/BillDogError.ts +24 -0
  270. package/src/models/CacheFetchPolicy.ts +13 -0
  271. package/src/models/CustomProduct.ts +33 -0
  272. package/src/models/CustomerInfo.ts +26 -0
  273. package/src/models/Delegate.ts +22 -0
  274. package/src/models/EntitlementInfo.ts +27 -0
  275. package/src/models/Placement.ts +50 -0
  276. package/src/models/PurchaseParams.ts +81 -0
  277. package/src/models/PurchaseResult.ts +32 -0
  278. package/src/models/RestoreResult.ts +27 -0
  279. package/src/models/RestoredItem.ts +25 -0
  280. package/src/modules/ABTest.ts +131 -0
  281. package/src/modules/Analytics.ts +227 -0
  282. package/src/modules/Survey.ts +126 -0
  283. package/src/modules/VirtualCurrency.ts +223 -0
  284. package/src/murmur.ts +102 -0
  285. package/src/notifications/LiveActivitiesManager.ts +140 -0
  286. package/src/notifications/NotificationScheduler.ts +292 -0
  287. package/src/notifications/PurchaseNotificationHandler.ts +67 -0
  288. package/src/notifications/useDeviceToken.ts +116 -0
  289. package/src/notifications/useLiveActivity.ts +125 -0
  290. package/src/review/ReviewAnalytics.ts +89 -0
  291. package/src/review/ReviewManager.ts +355 -0
  292. package/src/review/ReviewTimingManager.ts +265 -0
  293. package/src/survey-core/types.ts +244 -0
  294. package/src/types/ambient.d.ts +9 -0
  295. package/src/types.ts +680 -0
  296. package/src/utils/ApiClient.ts +163 -0
  297. package/src/utils/CSSConverter.ts +552 -0
  298. package/src/utils/animations.ts +232 -0
  299. package/src/utils/calendarIntegration.ts +113 -0
  300. package/src/utils/configurationResolver.ts +106 -0
  301. package/src/utils/deviceDetection.ts +83 -0
  302. package/src/utils/hapticFeedback.ts +55 -0
  303. package/src/utils/iconMapper.ts +102 -0
  304. package/src/utils/notificationPermissions.ts +48 -0
  305. package/src/utils/priceFormatting.ts +119 -0
  306. package/src/utils/shareSheet.ts +55 -0
  307. package/src/utils/subscriptionUpgrade.ts +183 -0
  308. package/src/valueUtils.ts +108 -0
  309. package/src/xFlowTags.ts +463 -0
package/dist/murmur.js ADDED
@@ -0,0 +1,104 @@
1
+ "use strict";
2
+ /**
3
+ * MurmurHash3 (x86_32) — the ONE canonical deterministic bucketing hash.
4
+ *
5
+ * React Native port of the backend canonical `murmurhash3`
6
+ * (`supabase/functions/_shared/edge-serving/pure.ts`) and the dashboard copy
7
+ * (`src/lib/murmur.ts`). Used to derive the render-time `user.seed` Dynamic
8
+ * Values variable so a user buckets IDENTICALLY on every surface.
9
+ *
10
+ * RN-SPECIFIC: uses a manual UTF-8 encoder instead of `TextEncoder`, because
11
+ * Hermes historically ships without `TextEncoder`. The bytes it produces are
12
+ * identical to `TextEncoder().encode(...)` for the fixture inputs (incl.
13
+ * surrogate-pair emoji), so it stays pinned to the same corpus.
14
+ *
15
+ * CONTRACT (do not change without regenerating the fixture on ALL ports):
16
+ * user.seed = murmurhash3(appUserId) % 1000 → range 0..999
17
+ *
18
+ * Conformance-pinned to `native-sdks/_test-fixtures/conformance/core_user_seed.json`.
19
+ * Never validated against another SDK port.
20
+ */
21
+ Object.defineProperty(exports, "__esModule", { value: true });
22
+ exports.USER_SEED_MODULUS = void 0;
23
+ exports.murmurhash3 = murmurhash3;
24
+ exports.userSeedBucket = userSeedBucket;
25
+ /** UTF-8 encode without depending on TextEncoder (Hermes-safe). */
26
+ function utf8Bytes(str) {
27
+ const bytes = [];
28
+ for (let i = 0; i < str.length; i++) {
29
+ let code = str.charCodeAt(i);
30
+ if (code < 0x80) {
31
+ bytes.push(code);
32
+ }
33
+ else if (code < 0x800) {
34
+ bytes.push(0xc0 | (code >> 6), 0x80 | (code & 0x3f));
35
+ }
36
+ else if (code >= 0xd800 && code <= 0xdbff) {
37
+ // High surrogate — must be followed by a low surrogate.
38
+ const lo = str.charCodeAt(i + 1);
39
+ if (lo >= 0xdc00 && lo <= 0xdfff) {
40
+ i++;
41
+ code = 0x10000 + ((code - 0xd800) << 10) + (lo - 0xdc00);
42
+ bytes.push(0xf0 | (code >> 18), 0x80 | ((code >> 12) & 0x3f), 0x80 | ((code >> 6) & 0x3f), 0x80 | (code & 0x3f));
43
+ }
44
+ else {
45
+ // Lone high surrogate → U+FFFD replacement char, matching TextEncoder.
46
+ bytes.push(0xef, 0xbf, 0xbd);
47
+ }
48
+ }
49
+ else if (code >= 0xdc00 && code <= 0xdfff) {
50
+ // Lone low surrogate → U+FFFD, matching TextEncoder.
51
+ bytes.push(0xef, 0xbf, 0xbd);
52
+ }
53
+ else {
54
+ bytes.push(0xe0 | (code >> 12), 0x80 | ((code >> 6) & 0x3f), 0x80 | (code & 0x3f));
55
+ }
56
+ }
57
+ return bytes;
58
+ }
59
+ function murmurhash3(key, seed = 0) {
60
+ const keyBytes = utf8Bytes(key);
61
+ let h1 = seed;
62
+ const c1 = 0xcc9e2d51;
63
+ const c2 = 0x1b873593;
64
+ const blocks = Math.floor(keyBytes.length / 4);
65
+ for (let i = 0; i < blocks; i++) {
66
+ let k1 = keyBytes[i * 4] | (keyBytes[i * 4 + 1] << 8) | (keyBytes[i * 4 + 2] << 16) | (keyBytes[i * 4 + 3] << 24);
67
+ k1 = Math.imul(k1, c1);
68
+ k1 = (k1 << 15) | (k1 >>> 17);
69
+ k1 = Math.imul(k1, c2);
70
+ h1 ^= k1;
71
+ h1 = (h1 << 13) | (h1 >>> 19);
72
+ h1 = Math.imul(h1, 5) + 0xe6546b64;
73
+ }
74
+ let k1 = 0;
75
+ const offset = blocks * 4;
76
+ switch (keyBytes.length % 4) {
77
+ case 3:
78
+ k1 ^= keyBytes[offset + 2] << 16;
79
+ /* falls through */
80
+ case 2:
81
+ k1 ^= keyBytes[offset + 1] << 8;
82
+ /* falls through */
83
+ case 1:
84
+ k1 ^= keyBytes[offset];
85
+ k1 = Math.imul(k1, c1);
86
+ k1 = (k1 << 15) | (k1 >>> 17);
87
+ k1 = Math.imul(k1, c2);
88
+ h1 ^= k1;
89
+ }
90
+ h1 ^= keyBytes.length;
91
+ h1 ^= h1 >>> 16;
92
+ h1 = Math.imul(h1, 0x85ebca6b);
93
+ h1 ^= h1 >>> 13;
94
+ h1 = Math.imul(h1, 0xc2b2ae35);
95
+ h1 ^= h1 >>> 16;
96
+ return h1 >>> 0;
97
+ }
98
+ exports.USER_SEED_MODULUS = 1000;
99
+ /** Canonical `user.seed` derivation: 0..999 bucket from a stable user id. */
100
+ function userSeedBucket(appUserId) {
101
+ if (!appUserId)
102
+ return 0;
103
+ return murmurhash3(appUserId) % exports.USER_SEED_MODULUS;
104
+ }
@@ -0,0 +1,47 @@
1
+ export interface LiveActivityConfig {
2
+ activityType: string;
3
+ attributes: Record<string, any>;
4
+ contentState: Record<string, any>;
5
+ staleDate?: Date;
6
+ dismissalDate?: Date;
7
+ }
8
+ export interface LiveActivityUpdate {
9
+ contentState: Record<string, any>;
10
+ staleDate?: Date;
11
+ }
12
+ /**
13
+ * Manager for iOS Live Activities
14
+ * Only available on iOS 16.1+
15
+ */
16
+ export declare class LiveActivitiesManager {
17
+ private static instance;
18
+ private constructor();
19
+ static getInstance(): LiveActivitiesManager;
20
+ /**
21
+ * Check if Live Activities are supported
22
+ */
23
+ isSupported(): boolean;
24
+ /**
25
+ * Check if Live Activities are enabled by the user
26
+ */
27
+ areActivitiesEnabled(): Promise<boolean>;
28
+ /**
29
+ * Start a new Live Activity
30
+ * Returns the activity ID
31
+ */
32
+ startActivity(config: LiveActivityConfig): Promise<string>;
33
+ /**
34
+ * Update an existing Live Activity
35
+ */
36
+ updateActivity(activityId: string, update: LiveActivityUpdate): Promise<void>;
37
+ /**
38
+ * End a Live Activity
39
+ */
40
+ endActivity(activityId: string, finalState?: Record<string, any>, dismissalPolicy?: 'default' | 'immediate' | 'after'): Promise<void>;
41
+ /**
42
+ * Get all active Live Activities
43
+ * Returns array of activity IDs
44
+ */
45
+ getActiveActivities(): Promise<string[]>;
46
+ }
47
+ export declare const liveActivities: LiveActivitiesManager;
@@ -0,0 +1,106 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.liveActivities = exports.LiveActivitiesManager = void 0;
4
+ const react_native_1 = require("react-native");
5
+ const { BillDogLiveActivities } = react_native_1.NativeModules;
6
+ /**
7
+ * Manager for iOS Live Activities
8
+ * Only available on iOS 16.1+
9
+ */
10
+ class LiveActivitiesManager {
11
+ constructor() { }
12
+ static getInstance() {
13
+ if (!LiveActivitiesManager.instance) {
14
+ LiveActivitiesManager.instance = new LiveActivitiesManager();
15
+ }
16
+ return LiveActivitiesManager.instance;
17
+ }
18
+ /**
19
+ * Check if Live Activities are supported
20
+ */
21
+ isSupported() {
22
+ return react_native_1.Platform.OS === 'ios' && react_native_1.Platform.Version >= '16.2' && !!BillDogLiveActivities;
23
+ }
24
+ /**
25
+ * Check if Live Activities are enabled by the user
26
+ */
27
+ async areActivitiesEnabled() {
28
+ if (!this.isSupported()) {
29
+ return false;
30
+ }
31
+ try {
32
+ return await BillDogLiveActivities.areActivitiesEnabled();
33
+ }
34
+ catch (error) {
35
+ console.error('[LiveActivitiesManager] Error checking enabled status:', error);
36
+ return false;
37
+ }
38
+ }
39
+ /**
40
+ * Start a new Live Activity
41
+ * Returns the activity ID
42
+ */
43
+ async startActivity(config) {
44
+ var _a, _b;
45
+ if (!this.isSupported()) {
46
+ throw new Error('Live Activities are not supported on this platform');
47
+ }
48
+ try {
49
+ const activityId = await BillDogLiveActivities.startActivity(config.activityType, config.attributes, config.contentState, (_a = config.staleDate) === null || _a === void 0 ? void 0 : _a.toISOString(), (_b = config.dismissalDate) === null || _b === void 0 ? void 0 : _b.toISOString());
50
+ return activityId;
51
+ }
52
+ catch (error) {
53
+ console.error('[LiveActivitiesManager] Error starting activity:', error);
54
+ throw error;
55
+ }
56
+ }
57
+ /**
58
+ * Update an existing Live Activity
59
+ */
60
+ async updateActivity(activityId, update) {
61
+ var _a;
62
+ if (!this.isSupported()) {
63
+ throw new Error('Live Activities are not supported on this platform');
64
+ }
65
+ try {
66
+ await BillDogLiveActivities.updateActivity(activityId, update.contentState, (_a = update.staleDate) === null || _a === void 0 ? void 0 : _a.toISOString());
67
+ }
68
+ catch (error) {
69
+ console.error('[LiveActivitiesManager] Error updating activity:', error);
70
+ throw error;
71
+ }
72
+ }
73
+ /**
74
+ * End a Live Activity
75
+ */
76
+ async endActivity(activityId, finalState, dismissalPolicy = 'default') {
77
+ if (!this.isSupported()) {
78
+ throw new Error('Live Activities are not supported on this platform');
79
+ }
80
+ try {
81
+ await BillDogLiveActivities.endActivity(activityId, finalState, dismissalPolicy);
82
+ }
83
+ catch (error) {
84
+ console.error('[LiveActivitiesManager] Error ending activity:', error);
85
+ throw error;
86
+ }
87
+ }
88
+ /**
89
+ * Get all active Live Activities
90
+ * Returns array of activity IDs
91
+ */
92
+ async getActiveActivities() {
93
+ if (!this.isSupported()) {
94
+ return [];
95
+ }
96
+ try {
97
+ return await BillDogLiveActivities.getActiveActivities();
98
+ }
99
+ catch (error) {
100
+ console.error('[LiveActivitiesManager] Error getting active activities:', error);
101
+ return [];
102
+ }
103
+ }
104
+ }
105
+ exports.LiveActivitiesManager = LiveActivitiesManager;
106
+ exports.liveActivities = LiveActivitiesManager.getInstance();
@@ -0,0 +1,55 @@
1
+ /**
2
+ * Handles scheduling and managing trial reminder notifications for React Native.
3
+ *
4
+ * All API calls route through `ApiClient` → `BillDogConfiguration.apiBaseUrl`
5
+ * (the single branded host, `https://api.billdog.io/v1`).
6
+ */
7
+ export declare class NotificationScheduler {
8
+ private static instance;
9
+ private constructor();
10
+ static getInstance(): NotificationScheduler;
11
+ private configure;
12
+ requestPermissions(): Promise<boolean>;
13
+ checkPermissions(): Promise<boolean>;
14
+ /**
15
+ * Schedule a trial reminder notification.
16
+ *
17
+ * @param apiKey - @deprecated Resolved from BillDogConfiguration if omitted
18
+ */
19
+ scheduleTrialNotification(subscription: Subscription, config: NotificationConfig, apiKey?: string): Promise<void>;
20
+ cancelNotification(subscriptionId: string, apiKey?: string): Promise<void>;
21
+ getScheduledNotifications(): Promise<any[]>;
22
+ /**
23
+ * Update subscription notification status via ApiClient.
24
+ */
25
+ private updateSubscriptionNotificationStatus;
26
+ }
27
+ /**
28
+ * Type definitions
29
+ */
30
+ export interface NotificationConfig {
31
+ enabled: boolean;
32
+ dayOfTrial: number;
33
+ title: string;
34
+ subtitle?: string;
35
+ body: string;
36
+ requestPermissions: boolean;
37
+ removeNotificationEnabled?: boolean;
38
+ sound?: string;
39
+ badge?: number;
40
+ }
41
+ export interface Subscription {
42
+ id: string;
43
+ isTrial: boolean;
44
+ purchasedAt?: string;
45
+ expiresAt?: string;
46
+ notificationScheduledAt?: string;
47
+ notificationSentAt?: string;
48
+ notificationCancelledAt?: string;
49
+ }
50
+ export declare const requestNotificationPermissions: () => Promise<boolean>;
51
+ export declare const checkNotificationPermissions: () => Promise<boolean>;
52
+ export declare const scheduleTrialNotification: (subscription: Subscription, config: NotificationConfig, apiKey?: string) => Promise<void>;
53
+ export declare const cancelTrialNotification: (subscriptionId: string, apiKey?: string) => Promise<void>;
54
+ export declare const getScheduledNotifications: () => Promise<any[]>;
55
+ export { useDeviceToken, registerDeviceToken } from './useDeviceToken';
@@ -0,0 +1,199 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.registerDeviceToken = exports.useDeviceToken = exports.getScheduledNotifications = exports.cancelTrialNotification = exports.scheduleTrialNotification = exports.checkNotificationPermissions = exports.requestNotificationPermissions = exports.NotificationScheduler = void 0;
7
+ const react_native_1 = require("react-native");
8
+ const react_native_push_notification_1 = __importDefault(require("react-native-push-notification"));
9
+ const push_notification_ios_1 = __importDefault(require("@react-native-community/push-notification-ios"));
10
+ const ApiClient_1 = require("../utils/ApiClient");
11
+ /**
12
+ * Handles scheduling and managing trial reminder notifications for React Native.
13
+ *
14
+ * All API calls route through `ApiClient` → `BillDogConfiguration.apiBaseUrl`
15
+ * (the single branded host, `https://api.billdog.io/v1`).
16
+ */
17
+ class NotificationScheduler {
18
+ constructor() {
19
+ this.configure();
20
+ }
21
+ static getInstance() {
22
+ if (!NotificationScheduler.instance) {
23
+ NotificationScheduler.instance = new NotificationScheduler();
24
+ }
25
+ return NotificationScheduler.instance;
26
+ }
27
+ configure() {
28
+ react_native_push_notification_1.default.configure({
29
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any -- callback shape comes from the optional, untyped react-native-push-notification peer dep
30
+ onNotification: (notification) => {
31
+ console.log('Notification received:', notification);
32
+ if (react_native_1.Platform.OS === 'ios') {
33
+ notification.finish(push_notification_ios_1.default.FetchResult.NoData);
34
+ }
35
+ },
36
+ permissions: {
37
+ alert: true,
38
+ badge: true,
39
+ sound: true,
40
+ },
41
+ popInitialNotification: true,
42
+ requestPermissions: false,
43
+ });
44
+ if (react_native_1.Platform.OS === 'android') {
45
+ react_native_push_notification_1.default.createChannel({
46
+ channelId: 'trial-reminders',
47
+ channelName: 'Trial Reminders',
48
+ channelDescription: 'Notifications about your trial subscription',
49
+ importance: 4,
50
+ vibrate: true,
51
+ }, (created) => console.log(`Channel created: ${created}`));
52
+ }
53
+ }
54
+ async requestPermissions() {
55
+ if (react_native_1.Platform.OS === 'ios') {
56
+ return new Promise((resolve) => {
57
+ react_native_push_notification_1.default.requestPermissions((permissions) => {
58
+ resolve(permissions.alert === true);
59
+ });
60
+ });
61
+ }
62
+ else if (react_native_1.Platform.OS === 'android') {
63
+ if (react_native_1.Platform.Version >= 33) {
64
+ const granted = await react_native_1.PermissionsAndroid.request(react_native_1.PermissionsAndroid.PERMISSIONS.POST_NOTIFICATIONS);
65
+ return granted === react_native_1.PermissionsAndroid.RESULTS.GRANTED;
66
+ }
67
+ return true;
68
+ }
69
+ return false;
70
+ }
71
+ async checkPermissions() {
72
+ return new Promise((resolve) => {
73
+ react_native_push_notification_1.default.checkPermissions((permissions) => {
74
+ resolve(permissions.alert === true || permissions.alert === 1);
75
+ });
76
+ });
77
+ }
78
+ /**
79
+ * Schedule a trial reminder notification.
80
+ *
81
+ * @param apiKey - @deprecated Resolved from BillDogConfiguration if omitted
82
+ */
83
+ async scheduleTrialNotification(subscription, config, apiKey) {
84
+ if (!subscription.isTrial) {
85
+ console.warn('⚠️ Not a trial subscription, skipping notification');
86
+ throw new Error('Not a trial subscription');
87
+ }
88
+ if (!subscription.expiresAt || new Date(subscription.expiresAt) < new Date()) {
89
+ console.warn('⚠️ Trial already expired, skipping notification');
90
+ throw new Error('Trial already expired');
91
+ }
92
+ if (!subscription.purchasedAt) {
93
+ console.warn('⚠️ Missing trial start date, skipping notification');
94
+ throw new Error('Missing trial start date');
95
+ }
96
+ const purchaseDate = new Date(subscription.purchasedAt);
97
+ const notificationDate = new Date(purchaseDate);
98
+ notificationDate.setDate(notificationDate.getDate() + config.dayOfTrial);
99
+ if (notificationDate < new Date()) {
100
+ console.warn(`⚠️ Notification date is in the past (Day ${config.dayOfTrial} was ${notificationDate}), skipping`);
101
+ throw new Error('Notification date in the past');
102
+ }
103
+ if (notificationDate > new Date(subscription.expiresAt)) {
104
+ console.warn('⚠️ Notification date is after trial expiration, skipping');
105
+ throw new Error('Notification date after expiration');
106
+ }
107
+ if (subscription.notificationScheduledAt) {
108
+ console.warn(`⚠️ Notification already scheduled at ${subscription.notificationScheduledAt}`);
109
+ throw new Error('Notification already scheduled');
110
+ }
111
+ const hasPermission = await this.checkPermissions();
112
+ if (!hasPermission) {
113
+ if (config.requestPermissions) {
114
+ const granted = await this.requestPermissions();
115
+ if (!granted) {
116
+ throw new Error('Notification permission denied');
117
+ }
118
+ }
119
+ else {
120
+ throw new Error('Notification permission not granted');
121
+ }
122
+ }
123
+ react_native_push_notification_1.default.localNotificationSchedule({
124
+ id: `trial_reminder_${subscription.id}`,
125
+ channelId: 'trial-reminders',
126
+ title: config.title,
127
+ message: config.body,
128
+ date: notificationDate,
129
+ allowWhileIdle: true,
130
+ userInfo: {
131
+ subscription_id: subscription.id,
132
+ notification_type: 'trial_reminder',
133
+ day_of_trial: config.dayOfTrial,
134
+ },
135
+ ...(config.subtitle && react_native_1.Platform.OS === 'ios' ? { subtitle: config.subtitle } : {}),
136
+ ...(config.sound ? { soundName: config.sound } : {}),
137
+ ...(config.badge ? { number: config.badge } : {}),
138
+ });
139
+ // Update subscription via ApiClient
140
+ await this.updateSubscriptionNotificationStatus(subscription.id, { scheduledAt: new Date() }, apiKey);
141
+ console.log(`✅ Scheduled trial reminder notification for Day ${config.dayOfTrial} at ${notificationDate}`);
142
+ }
143
+ async cancelNotification(subscriptionId, apiKey) {
144
+ react_native_push_notification_1.default.cancelLocalNotification(`trial_reminder_${subscriptionId}`);
145
+ await this.updateSubscriptionNotificationStatus(subscriptionId, { cancelledAt: new Date() }, apiKey);
146
+ console.log('✅ Cancelled trial reminder notification');
147
+ }
148
+ async getScheduledNotifications() {
149
+ return new Promise((resolve) => {
150
+ react_native_push_notification_1.default.getScheduledLocalNotifications((notifications) => {
151
+ resolve(notifications);
152
+ });
153
+ });
154
+ }
155
+ /**
156
+ * Update subscription notification status via ApiClient.
157
+ */
158
+ async updateSubscriptionNotificationStatus(subscriptionId, updates, apiKey) {
159
+ const body = {};
160
+ if (updates.scheduledAt) {
161
+ body.notification_scheduled_at = updates.scheduledAt.toISOString();
162
+ }
163
+ if (updates.sentAt) {
164
+ body.notification_sent_at = updates.sentAt.toISOString();
165
+ }
166
+ if (updates.cancelledAt) {
167
+ body.notification_cancelled_at = updates.cancelledAt.toISOString();
168
+ }
169
+ if (Object.keys(body).length === 0)
170
+ return;
171
+ try {
172
+ await ApiClient_1.ApiClient.post('update-subscription-notification', {
173
+ subscription_id: subscriptionId,
174
+ ...body,
175
+ }, {
176
+ apiKey,
177
+ });
178
+ }
179
+ catch (error) {
180
+ console.warn('⚠️ Failed to update subscription status:', error);
181
+ }
182
+ }
183
+ }
184
+ exports.NotificationScheduler = NotificationScheduler;
185
+ // Convenience exports
186
+ const requestNotificationPermissions = () => NotificationScheduler.getInstance().requestPermissions();
187
+ exports.requestNotificationPermissions = requestNotificationPermissions;
188
+ const checkNotificationPermissions = () => NotificationScheduler.getInstance().checkPermissions();
189
+ exports.checkNotificationPermissions = checkNotificationPermissions;
190
+ const scheduleTrialNotification = (subscription, config, apiKey) => NotificationScheduler.getInstance().scheduleTrialNotification(subscription, config, apiKey);
191
+ exports.scheduleTrialNotification = scheduleTrialNotification;
192
+ const cancelTrialNotification = (subscriptionId, apiKey) => NotificationScheduler.getInstance().cancelNotification(subscriptionId, apiKey);
193
+ exports.cancelTrialNotification = cancelTrialNotification;
194
+ const getScheduledNotifications = () => NotificationScheduler.getInstance().getScheduledNotifications();
195
+ exports.getScheduledNotifications = getScheduledNotifications;
196
+ // Re-export device token registration
197
+ var useDeviceToken_1 = require("./useDeviceToken");
198
+ Object.defineProperty(exports, "useDeviceToken", { enumerable: true, get: function () { return useDeviceToken_1.useDeviceToken; } });
199
+ Object.defineProperty(exports, "registerDeviceToken", { enumerable: true, get: function () { return useDeviceToken_1.registerDeviceToken; } });
@@ -0,0 +1,24 @@
1
+ export interface PurchaseNotificationConfig {
2
+ /** @deprecated Use BillDogConfiguration.configure({ apiKey }) instead */
3
+ apiKey?: string;
4
+ }
5
+ export interface PurchaseDetails {
6
+ subscriptionId: string;
7
+ userId: string;
8
+ projectId: string;
9
+ productId: string;
10
+ platform: 'ios' | 'android';
11
+ }
12
+ /**
13
+ * Handles notification cancellation when purchases are completed.
14
+ *
15
+ * Resolves API endpoint from BillDogConfiguration by default.
16
+ */
17
+ export declare class PurchaseNotificationHandler {
18
+ /** @deprecated */
19
+ private apiKey?;
20
+ constructor(config?: PurchaseNotificationConfig);
21
+ handlePurchaseCompleted(details: PurchaseDetails): Promise<boolean>;
22
+ private cancelLocalNotification;
23
+ private cancelRemoteNotification;
24
+ }
@@ -0,0 +1,55 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.PurchaseNotificationHandler = void 0;
7
+ const react_native_push_notification_1 = __importDefault(require("react-native-push-notification"));
8
+ const ApiClient_1 = require("../utils/ApiClient");
9
+ /**
10
+ * Handles notification cancellation when purchases are completed.
11
+ *
12
+ * Resolves API endpoint from BillDogConfiguration by default.
13
+ */
14
+ class PurchaseNotificationHandler {
15
+ constructor(config = {}) {
16
+ this.apiKey = config.apiKey;
17
+ }
18
+ async handlePurchaseCompleted(details) {
19
+ try {
20
+ this.cancelLocalNotification(details.subscriptionId);
21
+ await this.cancelRemoteNotification(details);
22
+ return true;
23
+ }
24
+ catch (error) {
25
+ console.error('[PurchaseNotificationHandler] Error handling purchase:', error);
26
+ throw error;
27
+ }
28
+ }
29
+ cancelLocalNotification(subscriptionId) {
30
+ const notificationId = `trial-reminder-${subscriptionId}`;
31
+ react_native_push_notification_1.default.cancelLocalNotification(notificationId);
32
+ react_native_push_notification_1.default.cancelAllLocalNotifications();
33
+ console.log('[PurchaseNotificationHandler] Cancelled local notification:', notificationId);
34
+ }
35
+ async cancelRemoteNotification(details) {
36
+ try {
37
+ const result = await ApiClient_1.ApiClient.post('handle-purchase-notification', {
38
+ subscriptionId: details.subscriptionId,
39
+ userId: details.userId,
40
+ projectId: details.projectId,
41
+ productId: details.productId,
42
+ platform: details.platform,
43
+ purchaseDate: new Date().toISOString(),
44
+ }, {
45
+ apiKey: this.apiKey,
46
+ });
47
+ console.log('[PurchaseNotificationHandler] Successfully updated backend:', result);
48
+ }
49
+ catch (error) {
50
+ console.error('[PurchaseNotificationHandler] Error updating backend:', error);
51
+ throw error;
52
+ }
53
+ }
54
+ }
55
+ exports.PurchaseNotificationHandler = PurchaseNotificationHandler;
@@ -0,0 +1,36 @@
1
+ interface UseDeviceTokenOptions {
2
+ userId: string;
3
+ projectId: string;
4
+ /** @deprecated Use BillDogConfiguration.configure({ apiKey }) instead */
5
+ apiKey?: string;
6
+ onTokenRegistered?: (token: string) => void;
7
+ onError?: (error: Error) => void;
8
+ }
9
+ /**
10
+ * Hook to register device token for push notifications.
11
+ * Automatically registers the device token when the component mounts.
12
+ *
13
+ * Credentials are resolved from `BillDogConfiguration` by default.
14
+ *
15
+ * @example
16
+ * ```tsx
17
+ * import { useDeviceToken } from '@billdog.io/react-native';
18
+ *
19
+ * function App() {
20
+ * useDeviceToken({
21
+ * userId: 'user-123',
22
+ * projectId: 'project-456',
23
+ * onTokenRegistered: (token) => console.log('Token registered:', token),
24
+ * });
25
+ *
26
+ * return <YourApp />;
27
+ * }
28
+ * ```
29
+ */
30
+ export declare function useDeviceToken({ userId, projectId, apiKey: apiKeyOverride, onTokenRegistered, onError, }: UseDeviceTokenOptions): void;
31
+ /**
32
+ * Manually register a device token.
33
+ * Resolves the endpoint from BillDogConfiguration (api.billdog.io/v1).
34
+ */
35
+ export declare function registerDeviceToken(token: string, userId: string, projectId: string, apiKey?: string, platform?: 'ios' | 'android'): Promise<void>;
36
+ export {};