@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
@@ -0,0 +1,918 @@
1
+ "use strict";
2
+ /**
3
+ * BillDog — top-level RN facade.
4
+ *
5
+ * Spec: PUR-063, PUR-064, PUR-080..085, PUR-121, PUR-122, PUR-140..146,
6
+ * PUR-224, PUR-350, PUR-360, PUR-362, PUR-363, PUR-364
7
+ * (.lovable/purchase-conformance-spec.md)
8
+ * Standard: mem://architecture/react-native/sdk-unified-standard
9
+ * mem://architecture/customer-info-cache-standard
10
+ * mem://architecture/entitlements-authoritative-standard
11
+ * mem://architecture/purchase-conformance-standard
12
+ *
13
+ * Slice J (PUR-364) propagates the v1.4 purchase parity surface to the RN
14
+ * bridge with iOS/Android wire parity:
15
+ * - `purchase(params)` — typed PurchaseParams, returns canonical PurchaseResult
16
+ * - `purchase(custom)` — Superwall-style non-StoreKit products via host controller
17
+ * - `setPurchaseController(...)` — JS-side controller for EXTERNAL/CUSTOM flows
18
+ * - `setProxyURL` / `getProxyURL` — self-hosted proxy
19
+ * - `canMakePayments`, `presentCodeRedemptionSheet`,
20
+ * `checkTrialOrIntroDiscountEligibility`, `onStorefrontChange`
21
+ * - 14-provider attribution matrix + `collectDeviceIdentifiers`
22
+ *
23
+ * Every method gracefully falls back when `NativeModules.BillDog` is null so
24
+ * consumer apps compile against the contract before the native bridge is wired
25
+ * in their host project. The facade NEVER throws across the public boundary —
26
+ * store/network errors are surfaced as typed result unions.
27
+ */
28
+ var _a, _b;
29
+ Object.defineProperty(exports, "__esModule", { value: true });
30
+ exports.PurchaseParams = exports.BillDog = exports.SDK_VERSION = void 0;
31
+ const CacheFetchPolicy_1 = require("./models/CacheFetchPolicy");
32
+ const CustomerInfo_1 = require("./models/CustomerInfo");
33
+ const PurchaseParams_1 = require("./models/PurchaseParams");
34
+ Object.defineProperty(exports, "PurchaseParams", { enumerable: true, get: function () { return PurchaseParams_1.PurchaseParams; } });
35
+ const Analytics_1 = require("./modules/Analytics");
36
+ const BillDogConfiguration_1 = require("./BillDogConfiguration");
37
+ const ApiClient_1 = require("./utils/ApiClient");
38
+ // eslint-disable-next-line @typescript-eslint/no-var-requires
39
+ const RN = (() => {
40
+ try {
41
+ return require('react-native');
42
+ }
43
+ catch {
44
+ return null;
45
+ }
46
+ })();
47
+ const native = (_b = (_a = RN === null || RN === void 0 ? void 0 : RN.NativeModules) === null || _a === void 0 ? void 0 : _a.BillDog) !== null && _b !== void 0 ? _b : null;
48
+ // Optional AsyncStorage for persisting currentUserId across launches.
49
+ // Falls back to in-memory if the host app hasn't installed it.
50
+ const AsyncStorage = (() => {
51
+ try {
52
+ // eslint-disable-next-line @typescript-eslint/no-var-requires
53
+ return require('@react-native-async-storage/async-storage').default;
54
+ }
55
+ catch {
56
+ return null;
57
+ }
58
+ })();
59
+ // -----------------------------------------------------------------------------
60
+ // Identity API — Android parity (BillDog.kt: logIn, logOut, identify,
61
+ // isAnonymous, getAppUserId, isConfigured, setSandboxMode).
62
+ // Persisted across launches via AsyncStorage when available.
63
+ // -----------------------------------------------------------------------------
64
+ const CURRENT_USER_KEY = 'billdog.rn.currentUserId';
65
+ let _currentUserId = null;
66
+ // Rehydrate from storage on module load — best-effort, never throws.
67
+ if (AsyncStorage === null || AsyncStorage === void 0 ? void 0 : AsyncStorage.getItem) {
68
+ AsyncStorage.getItem(CURRENT_USER_KEY)
69
+ .then((id) => {
70
+ if (id && !_currentUserId)
71
+ _currentUserId = id;
72
+ })
73
+ .catch(() => {
74
+ /* ignore — degrade to in-memory */
75
+ });
76
+ }
77
+ class CustomerInfoEmitter {
78
+ constructor() {
79
+ this.listeners = new Set();
80
+ this.lastValue = null;
81
+ }
82
+ addListener(fn) {
83
+ this.listeners.add(fn);
84
+ if (this.lastValue)
85
+ fn(this.lastValue);
86
+ return { remove: () => this.listeners.delete(fn) };
87
+ }
88
+ emit(info) {
89
+ this.lastValue = info;
90
+ for (const l of this.listeners)
91
+ l(info);
92
+ }
93
+ get latest() {
94
+ return this.lastValue;
95
+ }
96
+ }
97
+ const customerInfoEmitter = new CustomerInfoEmitter();
98
+ const storefrontListeners = new Set();
99
+ let activeController = null;
100
+ let activeDelegate = null;
101
+ /** Stamp every receipt posted to BillDog's backend (PUR-185). */
102
+ const sourceForResult = () => activeController ? 'EXTERNAL' : 'INTERNAL';
103
+ const cancelledResult = { type: 'cancelled' };
104
+ const failedResult = (e, category = 'unknown') => {
105
+ var _a;
106
+ return ({
107
+ type: 'failed',
108
+ error: { category, message: (_a = e === null || e === void 0 ? void 0 : e.message) !== null && _a !== void 0 ? _a : 'Purchase failed' },
109
+ });
110
+ };
111
+ /**
112
+ * Best-effort POST of an EXTERNAL (host-controller) custom-product purchase
113
+ * to BillDog's `record-external-purchase` endpoint, which resolves the
114
+ * catalog product from `providerProductId`, grants the entitlement, and
115
+ * reports revenue with `source = EXTERNAL`.
116
+ */
117
+ async function recordExternalCustomPurchase(product, transactionId, transactionType = 'initial_purchase') {
118
+ const userId = exports.BillDog.getAppUserId();
119
+ if (!userId) {
120
+ console.warn('[BD-EXTERNAL] Skipping record — app user id unresolved');
121
+ return;
122
+ }
123
+ const txId = transactionId || `ext_${Math.random().toString(36).substring(2)}${Date.now()}`;
124
+ const body = {
125
+ user_id: userId,
126
+ transaction_id: txId,
127
+ product_id: product.id,
128
+ provider: product.provider,
129
+ provider_product_id: product.providerProductId,
130
+ purchase_date: new Date().toISOString(),
131
+ store: 'external',
132
+ price: product.price,
133
+ currency: product.currency,
134
+ transaction_type: transactionType,
135
+ };
136
+ try {
137
+ await ApiClient_1.ApiClient.post('record-external-purchase', body);
138
+ console.log(`[BD-EXTERNAL] Recorded custom purchase '${product.id}' (provider=${product.provider})`);
139
+ }
140
+ catch (e) {
141
+ console.warn(`[BD-EXTERNAL] record-external-purchase failed (not blocking):`, e);
142
+ }
143
+ }
144
+ /** SDK version constant — Android parity (BillDog.kt:51). */
145
+ exports.SDK_VERSION = '1.0.0-beta.2';
146
+ exports.BillDog = {
147
+ /** SDK version constant — re-exposed on the singleton for ergonomic access. */
148
+ SDK_VERSION: exports.SDK_VERSION,
149
+ // -------------------------------------------------------------------------
150
+ // PUR-350 / PUR-364 — Unified purchase API
151
+ // -------------------------------------------------------------------------
152
+ /**
153
+ * Purchase a product with typed `PurchaseParams`. Returns canonical
154
+ * `PurchaseResult` — NEVER throws across the public boundary.
155
+ *
156
+ * If a host `PurchaseController` is registered (see `setPurchaseController`),
157
+ * the controller drives the transaction and the receipt is stamped
158
+ * `source = EXTERNAL`. Otherwise the bundled native controller is used
159
+ * (`source = INTERNAL`).
160
+ */
161
+ async purchase(params) {
162
+ if (activeController) {
163
+ try {
164
+ return await activeController.purchase(params.productId);
165
+ }
166
+ catch (e) {
167
+ return failedResult(e);
168
+ }
169
+ }
170
+ if (!(native === null || native === void 0 ? void 0 : native.purchase)) {
171
+ // Bridge not wired in host app — return cancelled so the UI is consistent.
172
+ return cancelledResult;
173
+ }
174
+ try {
175
+ const raw = await native.purchase({ ...params, source: sourceForResult() });
176
+ if (raw && typeof raw.type === 'string')
177
+ return raw;
178
+ return cancelledResult;
179
+ }
180
+ catch (e) {
181
+ return failedResult(e);
182
+ }
183
+ },
184
+ /**
185
+ * PUR-363: Purchase a Superwall-style non-StoreKit / non-Play product.
186
+ * Routing is ONLY through a host-provided PurchaseController.
187
+ */
188
+ async purchaseCustom(product) {
189
+ if (!activeController) {
190
+ return failedResult(new Error('CustomProduct requires a host PurchaseController. Call BillDog.setPurchaseController() first.'));
191
+ }
192
+ try {
193
+ const raw = await activeController.purchase(product.providerProductId);
194
+ if (raw && raw.type === 'purchased') {
195
+ // Best-effort EXTERNAL recording so the entitlement is granted and revenue reported.
196
+ recordExternalCustomPurchase(product, raw.transactionId).catch(() => { });
197
+ exports.BillDog.getCustomerInfo('FETCH_CURRENT').catch(() => { });
198
+ }
199
+ return raw;
200
+ }
201
+ catch (e) {
202
+ return failedResult(e);
203
+ }
204
+ },
205
+ /** Get the currently-registered host PurchaseController, or null. */
206
+ getPurchaseController() {
207
+ return activeController;
208
+ },
209
+ /** Flush pending analytics events to the backend. */
210
+ async flushAnalytics() {
211
+ try {
212
+ await Analytics_1.AnalyticsManager.getInstance().flush();
213
+ }
214
+ catch { /* best-effort */ }
215
+ },
216
+ /** PUR-364: Register a host PurchaseController. Pass `null` to detach. */
217
+ setPurchaseController(controller) {
218
+ activeController = controller;
219
+ if (native === null || native === void 0 ? void 0 : native.setPurchaseControllerActive) {
220
+ try {
221
+ native.setPurchaseControllerActive(!!controller);
222
+ }
223
+ catch {
224
+ /* bridge no-op */
225
+ }
226
+ }
227
+ },
228
+ /**
229
+ * Restore previous purchases (PUR-080).
230
+ *
231
+ * - `{type:'restored', items: []}` — nothing to restore
232
+ * - `{type:'restored', items: [...]}` — items resurfaced
233
+ * - `{type:'failed', error: BillDogError}` — global failure
234
+ */
235
+ async restore() {
236
+ var _a, _b;
237
+ if (activeController) {
238
+ try {
239
+ return await activeController.restorePurchases();
240
+ }
241
+ catch (e) {
242
+ return {
243
+ type: 'failed',
244
+ error: { category: 'unknown', message: (_a = e === null || e === void 0 ? void 0 : e.message) !== null && _a !== void 0 ? _a : 'Restore failed' },
245
+ };
246
+ }
247
+ }
248
+ if (!(native === null || native === void 0 ? void 0 : native.restore)) {
249
+ return { type: 'restored', items: [] };
250
+ }
251
+ try {
252
+ const raw = await native.restore();
253
+ if (raw && (raw.type === 'restored' || raw.type === 'failed')) {
254
+ return raw;
255
+ }
256
+ return { type: 'restored', items: [] };
257
+ }
258
+ catch (e) {
259
+ return {
260
+ type: 'failed',
261
+ error: { category: 'unknown', message: (_b = e === null || e === void 0 ? void 0 : e.message) !== null && _b !== void 0 ? _b : 'Restore failed' },
262
+ };
263
+ }
264
+ },
265
+ // -------------------------------------------------------------------------
266
+ // PUR-141/224 — CustomerInfo
267
+ // -------------------------------------------------------------------------
268
+ async getCustomerInfo(policy = CacheFetchPolicy_1.DEFAULT_CACHE_FETCH_POLICY) {
269
+ if (!(native === null || native === void 0 ? void 0 : native.getCustomerInfo)) {
270
+ return customerInfoEmitter.latest;
271
+ }
272
+ try {
273
+ const info = (await native.getCustomerInfo(policy));
274
+ customerInfoEmitter.emit(info);
275
+ return info;
276
+ }
277
+ catch {
278
+ return customerInfoEmitter.latest;
279
+ }
280
+ },
281
+ customerInfoEmitter,
282
+ /**
283
+ * PUR-121: resolve entitlements unlocked by a [productId] from the local
284
+ * `productEntitlementMapping`. Used for instant gating.
285
+ */
286
+ entitlementsForProduct(productId) {
287
+ const info = customerInfoEmitter.latest;
288
+ if (!info)
289
+ return [];
290
+ return (0, CustomerInfo_1.entitlementsByProductId)(info, productId);
291
+ },
292
+ // -------------------------------------------------------------------------
293
+ // PUR-201 / PUR-202 / PUR-330 / PUR-037 — store capability surface
294
+ // -------------------------------------------------------------------------
295
+ /** PUR-201: Can the device transact at all? (parental controls, MDM) */
296
+ async canMakePayments() {
297
+ if (!(native === null || native === void 0 ? void 0 : native.canMakePayments))
298
+ return true;
299
+ try {
300
+ return !!(await native.canMakePayments());
301
+ }
302
+ catch {
303
+ return true;
304
+ }
305
+ },
306
+ /** PUR-330: Present the App Store promo code redemption sheet (iOS-only). */
307
+ async presentCodeRedemptionSheet() {
308
+ if (!(native === null || native === void 0 ? void 0 : native.presentCodeRedemptionSheet))
309
+ return;
310
+ try {
311
+ await native.presentCodeRedemptionSheet();
312
+ }
313
+ catch {
314
+ /* ignore */
315
+ }
316
+ },
317
+ /**
318
+ * PUR-037: Check trial / intro-discount eligibility for an array of product
319
+ * ids. Returns a map of `productId` -> `'eligible' | 'ineligible' | 'unknown'`.
320
+ */
321
+ async checkTrialOrIntroDiscountEligibility(productIds) {
322
+ if (!(native === null || native === void 0 ? void 0 : native.checkTrialOrIntroDiscountEligibility)) {
323
+ return Object.fromEntries(productIds.map((id) => [id, 'unknown']));
324
+ }
325
+ try {
326
+ return (await native.checkTrialOrIntroDiscountEligibility(productIds));
327
+ }
328
+ catch {
329
+ return Object.fromEntries(productIds.map((id) => [id, 'unknown']));
330
+ }
331
+ },
332
+ /** PUR-202: Subscribe to storefront country changes (iOS-only producer). */
333
+ onStorefrontChange(listener) {
334
+ storefrontListeners.add(listener);
335
+ if (native === null || native === void 0 ? void 0 : native.subscribeStorefront) {
336
+ try {
337
+ native.subscribeStorefront();
338
+ }
339
+ catch {
340
+ /* ignore */
341
+ }
342
+ }
343
+ return { remove: () => storefrontListeners.delete(listener) };
344
+ },
345
+ // -------------------------------------------------------------------------
346
+ // PUR-362 — Self-hosted proxy
347
+ // -------------------------------------------------------------------------
348
+ setProxyURL(url) {
349
+ if (!(native === null || native === void 0 ? void 0 : native.setProxyURL))
350
+ return;
351
+ try {
352
+ native.setProxyURL(url);
353
+ }
354
+ catch {
355
+ /* ignore */
356
+ }
357
+ },
358
+ // ---------------------------------------------------------------------------
359
+ // Consent (cross-SDK contract) — delegates to the native ConsentManager when the
360
+ // host wires the BillDog native module, and degrades to a no-op otherwise (this
361
+ // package is fallback-by-design; full native enforcement needs the BillDog native
362
+ // module + bridge registration on both platforms — tracked as a separate task).
363
+ // ---------------------------------------------------------------------------
364
+ setConsentRequired(required) {
365
+ if (!(native === null || native === void 0 ? void 0 : native.setConsentRequired))
366
+ return;
367
+ try {
368
+ native.setConsentRequired(required);
369
+ }
370
+ catch {
371
+ /* ignore */
372
+ }
373
+ },
374
+ setConsent(purpose, granted) {
375
+ if (!(native === null || native === void 0 ? void 0 : native.setConsent))
376
+ return;
377
+ try {
378
+ native.setConsent(purpose, granted);
379
+ }
380
+ catch {
381
+ /* ignore */
382
+ }
383
+ },
384
+ setConsentGiven(given) {
385
+ if (!(native === null || native === void 0 ? void 0 : native.setConsentGiven))
386
+ return;
387
+ try {
388
+ native.setConsentGiven(given);
389
+ }
390
+ catch {
391
+ /* ignore */
392
+ }
393
+ },
394
+ async consentHeaderValue() {
395
+ var _a;
396
+ if (!(native === null || native === void 0 ? void 0 : native.consentHeaderValue))
397
+ return null;
398
+ try {
399
+ return (_a = (await native.consentHeaderValue())) !== null && _a !== void 0 ? _a : null;
400
+ }
401
+ catch {
402
+ return null;
403
+ }
404
+ },
405
+ getProxyURL() {
406
+ var _a;
407
+ if (!(native === null || native === void 0 ? void 0 : native.getProxyURL))
408
+ return null;
409
+ try {
410
+ return (_a = native.getProxyURL()) !== null && _a !== void 0 ? _a : null;
411
+ }
412
+ catch {
413
+ return null;
414
+ }
415
+ },
416
+ // -------------------------------------------------------------------------
417
+ // PUR-360 — Attribution matrix (14 providers, EXACT parity with the native
418
+ // SDKs: BillDog.kt / BillDog.swift). Each convenience setter forwards the
419
+ // provider's attribution key to the native `setAttribution` bridge, which
420
+ // delegates to the matching consent-gated native setter.
421
+ //
422
+ // Two provider groups, both natively backed:
423
+ // - 11 "modern" providers routed through the native `setAttribution` map
424
+ // (CleverTap … Segment).
425
+ // - 3 MMP providers with dedicated native setters (Adjust, AppsFlyer,
426
+ // Firebase). They share the same JS/bridge funnel — the bridge maps their
427
+ // keys to `setAdjustId` / `setAppsflyerId` / `setFirebaseAppInstanceId`.
428
+ //
429
+ // NOTE: Branch, Amplitude and Singular are NOT supported natively and were
430
+ // removed (they were JS-only no-ops). `setIterableUserID` / `setFBAnonymousID`
431
+ // replace the previously-misnamed `setIterableID` / `setFirebaseAppInstanceID`.
432
+ // -------------------------------------------------------------------------
433
+ /**
434
+ * Set one or more attribution ids at once. Keys are the provider attribution
435
+ * keys (e.g. `mixpanelDistinctId`, `cleverTapId`, `iterableId`). Prefer the
436
+ * named convenience setters below unless batching.
437
+ */
438
+ setAttribution(data) {
439
+ if (!(native === null || native === void 0 ? void 0 : native.setAttribution))
440
+ return;
441
+ try {
442
+ native.setAttribution(data);
443
+ }
444
+ catch {
445
+ /* swallow — attribution is best-effort */
446
+ }
447
+ },
448
+ setCleverTapID: (id) => setAttributionKey('cleverTapId', id),
449
+ setMixpanelDistinctID: (id) => setAttributionKey('mixpanelDistinctId', id),
450
+ setOnesignalID: (id) => setAttributionKey('onesignalId', id),
451
+ setFBAnonymousID: (id) => setAttributionKey('fbAnonymousId', id),
452
+ setAirshipChannelID: (id) => setAttributionKey('airshipChannelId', id),
453
+ setMoEngageAnonymousID: (id) => setAttributionKey('moEngageAnonymousId', id),
454
+ setMparticleID: (id) => setAttributionKey('mparticleId', id),
455
+ setKochavaDeviceID: (id) => setAttributionKey('kochavaId', id),
456
+ setTenjinAnalyticsInstallationID: (id) => setAttributionKey('tenjinId', id),
457
+ setIterableUserID: (id) => setAttributionKey('iterableId', id),
458
+ setSegmentAnonymousID: (id) => setAttributionKey('segmentId', id),
459
+ // MMP providers — dedicated native setters, same JS/bridge funnel.
460
+ setAdjustId: (id) => setAttributionKey('adjustId', id),
461
+ setAppsflyerId: (id) => setAttributionKey('appsflyerId', id),
462
+ setFirebaseAppInstanceId: (id) => setAttributionKey('firebaseAppInstanceId', id),
463
+ /** Collect IDFA / GAID after consent has been granted. */
464
+ collectDeviceIdentifiers() {
465
+ if (!(native === null || native === void 0 ? void 0 : native.collectDeviceIdentifiers))
466
+ return;
467
+ try {
468
+ native.collectDeviceIdentifiers();
469
+ }
470
+ catch {
471
+ /* ignore */
472
+ }
473
+ },
474
+ // -------------------------------------------------------------------------
475
+ // Identity API — Android parity (BillDog.kt:782/807/845/890/894/325)
476
+ // -------------------------------------------------------------------------
477
+ /**
478
+ * Log in an app user. Persists the user id, propagates to the native bridge
479
+ * (if wired) and the analytics module. Throws on blank ids — mirrors KMP/Unity.
480
+ */
481
+ async logIn(appUserId) {
482
+ if (!appUserId || !appUserId.trim()) {
483
+ throw new Error('appUserId must be non-blank');
484
+ }
485
+ _currentUserId = appUserId;
486
+ if (AsyncStorage === null || AsyncStorage === void 0 ? void 0 : AsyncStorage.setItem) {
487
+ try {
488
+ await AsyncStorage.setItem(CURRENT_USER_KEY, appUserId);
489
+ }
490
+ catch {
491
+ /* ignore — degrade to in-memory */
492
+ }
493
+ }
494
+ if (native === null || native === void 0 ? void 0 : native.logIn) {
495
+ try {
496
+ await native.logIn(appUserId);
497
+ }
498
+ catch {
499
+ /* swallow — identity is also tracked locally */
500
+ }
501
+ }
502
+ try {
503
+ await Analytics_1.AnalyticsManager.getInstance().identify(appUserId);
504
+ }
505
+ catch {
506
+ /* analytics is best-effort */
507
+ }
508
+ },
509
+ /** Log out the current user and return to anonymous state. */
510
+ async logOut() {
511
+ _currentUserId = null;
512
+ if (AsyncStorage === null || AsyncStorage === void 0 ? void 0 : AsyncStorage.removeItem) {
513
+ try {
514
+ await AsyncStorage.removeItem(CURRENT_USER_KEY);
515
+ }
516
+ catch {
517
+ /* ignore */
518
+ }
519
+ }
520
+ if (native === null || native === void 0 ? void 0 : native.logOut) {
521
+ try {
522
+ await native.logOut();
523
+ }
524
+ catch {
525
+ /* swallow */
526
+ }
527
+ }
528
+ try {
529
+ await Analytics_1.AnalyticsManager.getInstance().reset();
530
+ }
531
+ catch {
532
+ /* best-effort */
533
+ }
534
+ },
535
+ /**
536
+ * Identify a user with optional attributes. Behaves as `logIn` plus an
537
+ * analytics super-properties update for the supplied attributes.
538
+ */
539
+ async identify(userId, attributes) {
540
+ await this.logIn(userId);
541
+ if (attributes && Object.keys(attributes).length > 0) {
542
+ try {
543
+ await Analytics_1.AnalyticsManager.getInstance().setSuperProperties(attributes);
544
+ }
545
+ catch {
546
+ /* analytics is best-effort */
547
+ }
548
+ }
549
+ },
550
+ /** True when no app user is currently logged in. */
551
+ isAnonymous() {
552
+ return !_currentUserId;
553
+ },
554
+ /** Returns the currently logged-in app user id, or null when anonymous. */
555
+ getAppUserId() {
556
+ return _currentUserId;
557
+ },
558
+ /**
559
+ * Mirrors Android `BillDog.isConfigured()` (BillDog.kt:325). Delegates to
560
+ * the configuration singleton so the apiKey-presence check lives in one place.
561
+ */
562
+ isConfigured() {
563
+ return BillDogConfiguration_1.BillDogConfiguration.isConfigured();
564
+ },
565
+ /**
566
+ * Cross-SDK parity stub matching KMP / Unity / Android. Toggles a local
567
+ * flag and forwards to the native bridge if wired; otherwise a documented
568
+ * no-op (sandbox is primarily controlled via API key prefix).
569
+ */
570
+ setSandboxMode(enabled) {
571
+ if (native === null || native === void 0 ? void 0 : native.setSandboxMode) {
572
+ try {
573
+ native.setSandboxMode(enabled);
574
+ }
575
+ catch {
576
+ /* ignore */
577
+ }
578
+ }
579
+ },
580
+ // -------------------------------------------------------------------------
581
+ // Placement registration — Android parity (BillDog.kt:981/990/1024/1938)
582
+ // -------------------------------------------------------------------------
583
+ /**
584
+ * Register a placement and run the canonical placement flow: fetch config →
585
+ * check entitlement → present paywall if needed. Returns a `PlacementResult`
586
+ * describing the outcome. Optional `handler` receives lifecycle callbacks
587
+ * mirroring Android's `PaywallPresentationHandler`.
588
+ *
589
+ * Returns `{ type: 'entitled' }` immediately if the user already holds the
590
+ * placement's required entitlement (no paywall shown). Returns
591
+ * `{ type: 'error', message }` on any failure — never throws across the
592
+ * public boundary.
593
+ */
594
+ async register(placementId, params, handler) {
595
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v;
596
+ if (!BillDogConfiguration_1.BillDogConfiguration.isConfigured()) {
597
+ const err = 'BillDog SDK not configured.';
598
+ (_a = handler === null || handler === void 0 ? void 0 : handler.onLoadingStateChange) === null || _a === void 0 ? void 0 : _a.call(handler, 'failed');
599
+ (_b = handler === null || handler === void 0 ? void 0 : handler.onError) === null || _b === void 0 ? void 0 : _b.call(handler, new Error(err));
600
+ (_c = handler === null || handler === void 0 ? void 0 : handler.onSkip) === null || _c === void 0 ? void 0 : _c.call(handler, 'error');
601
+ return { type: 'error', message: err };
602
+ }
603
+ (_d = handler === null || handler === void 0 ? void 0 : handler.onLoadingStateChange) === null || _d === void 0 ? void 0 : _d.call(handler, 'loading');
604
+ if (!(native === null || native === void 0 ? void 0 : native.registerPlacement)) {
605
+ // No native bridge — emit no-op success path so the contract is met.
606
+ (_e = handler === null || handler === void 0 ? void 0 : handler.onLoadingStateChange) === null || _e === void 0 ? void 0 : _e.call(handler, 'ready');
607
+ (_f = handler === null || handler === void 0 ? void 0 : handler.onSkip) === null || _f === void 0 ? void 0 : _f.call(handler, 'no_paywall_configured');
608
+ return { type: 'error', message: 'Native placement bridge not wired' };
609
+ }
610
+ try {
611
+ const raw = await native.registerPlacement({ placementId, params: params !== null && params !== void 0 ? params : {} });
612
+ const result = (raw && typeof raw.type === 'string'
613
+ ? raw
614
+ : { type: 'error', message: 'Malformed placement result' });
615
+ switch (result.type) {
616
+ case 'entitled':
617
+ (_g = handler === null || handler === void 0 ? void 0 : handler.onLoadingStateChange) === null || _g === void 0 ? void 0 : _g.call(handler, 'ready');
618
+ (_h = handler === null || handler === void 0 ? void 0 : handler.onSkip) === null || _h === void 0 ? void 0 : _h.call(handler, 'user_has_entitlement');
619
+ break;
620
+ case 'purchased':
621
+ case 'dismissed':
622
+ case 'restored':
623
+ (_j = handler === null || handler === void 0 ? void 0 : handler.onLoadingStateChange) === null || _j === void 0 ? void 0 : _j.call(handler, 'ready');
624
+ (_k = handler === null || handler === void 0 ? void 0 : handler.onPresent) === null || _k === void 0 ? void 0 : _k.call(handler, placementId);
625
+ if (result.type === 'purchased') {
626
+ (_l = handler === null || handler === void 0 ? void 0 : handler.onPurchaseSuccess) === null || _l === void 0 ? void 0 : _l.call(handler, result.productId);
627
+ }
628
+ (_m = handler === null || handler === void 0 ? void 0 : handler.onDismiss) === null || _m === void 0 ? void 0 : _m.call(handler, placementId);
629
+ (_o = handler === null || handler === void 0 ? void 0 : handler.onFinish) === null || _o === void 0 ? void 0 : _o.call(handler, placementId, true);
630
+ break;
631
+ case 'error':
632
+ (_p = handler === null || handler === void 0 ? void 0 : handler.onLoadingStateChange) === null || _p === void 0 ? void 0 : _p.call(handler, 'failed');
633
+ (_q = handler === null || handler === void 0 ? void 0 : handler.onError) === null || _q === void 0 ? void 0 : _q.call(handler, new Error(result.message));
634
+ (_r = handler === null || handler === void 0 ? void 0 : handler.onSkip) === null || _r === void 0 ? void 0 : _r.call(handler, 'error');
635
+ break;
636
+ }
637
+ return result;
638
+ }
639
+ catch (e) {
640
+ const msg = (_s = e === null || e === void 0 ? void 0 : e.message) !== null && _s !== void 0 ? _s : 'Placement registration failed';
641
+ (_t = handler === null || handler === void 0 ? void 0 : handler.onLoadingStateChange) === null || _t === void 0 ? void 0 : _t.call(handler, 'failed');
642
+ (_u = handler === null || handler === void 0 ? void 0 : handler.onError) === null || _u === void 0 ? void 0 : _u.call(handler, new Error(msg));
643
+ (_v = handler === null || handler === void 0 ? void 0 : handler.onSkip) === null || _v === void 0 ? void 0 : _v.call(handler, 'error');
644
+ return { type: 'error', message: msg };
645
+ }
646
+ },
647
+ /**
648
+ * Synchronous probe — does the current user have access to a placement?
649
+ * Returns `true` when the placement is unregistered or has no required
650
+ * entitlement (safe default matching Android's behaviour).
651
+ */
652
+ hasAccessForPlacement(placementId) {
653
+ if (!(native === null || native === void 0 ? void 0 : native.hasAccessForPlacement))
654
+ return true;
655
+ try {
656
+ return !!native.hasAccessForPlacement(placementId);
657
+ }
658
+ catch {
659
+ return true;
660
+ }
661
+ },
662
+ // Experiments & feature flags: the paywall-facade shim was removed. Use the
663
+ // standalone A/B module (BillDogABTest / ABTestManager) instead.
664
+ // ── In-app messages — Android parity (BillDog.kt:1969) ────────────
665
+ /** Open the IAM inbox / present a single message. */
666
+ async showInAppMessages(placementId) {
667
+ if (native === null || native === void 0 ? void 0 : native.showInAppMessages) {
668
+ try {
669
+ await native.showInAppMessages(placementId !== null && placementId !== void 0 ? placementId : null);
670
+ }
671
+ catch { /* ignore */ }
672
+ }
673
+ },
674
+ // ── Deep linking — Android parity (BillDog.kt:684) ────────────────
675
+ /** Route a deep link through the SDK. Returns true when handled. */
676
+ async handleDeepLink(uri) {
677
+ if (native === null || native === void 0 ? void 0 : native.handleDeepLink) {
678
+ try {
679
+ return !!(await native.handleDeepLink(uri));
680
+ }
681
+ catch { /* ignore */ }
682
+ }
683
+ return false;
684
+ },
685
+ // ── Component selection state — Android parity (BillDog.kt:1032–1044) ──
686
+ getSelectedProductIndex(componentId) {
687
+ if (native === null || native === void 0 ? void 0 : native.getSelectedProductIndex) {
688
+ try {
689
+ return native.getSelectedProductIndex(componentId);
690
+ }
691
+ catch { /* ignore */ }
692
+ }
693
+ return null;
694
+ },
695
+ setSelectedProductIndex(componentId, index) {
696
+ if (native === null || native === void 0 ? void 0 : native.setSelectedProductIndex) {
697
+ try {
698
+ native.setSelectedProductIndex(componentId, index);
699
+ }
700
+ catch { /* ignore */ }
701
+ }
702
+ },
703
+ // ── Theme override — Android parity (BillDog.kt:184) ──────────────
704
+ /** Apply runtime theme overrides. Map of token name → value. */
705
+ updateTheme(overrides) {
706
+ if (native === null || native === void 0 ? void 0 : native.updateTheme) {
707
+ try {
708
+ native.updateTheme(overrides);
709
+ }
710
+ catch { /* ignore */ }
711
+ }
712
+ },
713
+ /** Set the SDK-wide interface style. Pass `null` to follow system. */
714
+ setInterfaceStyle(style) {
715
+ if (native === null || native === void 0 ? void 0 : native.setInterfaceStyle) {
716
+ try {
717
+ native.setInterfaceStyle(style);
718
+ }
719
+ catch { /* ignore */ }
720
+ }
721
+ },
722
+ // ── Subscription management — Android parity (BillDog.kt:1500) ────
723
+ /**
724
+ * Open the platform-native subscription management UI. iOS routes to
725
+ * the App Store; Android routes to Play Store; web throws since no
726
+ * platform UI is available.
727
+ */
728
+ async showManageSubscriptions(subscriptionId) {
729
+ if (native === null || native === void 0 ? void 0 : native.showManageSubscriptions) {
730
+ try {
731
+ await native.showManageSubscriptions(subscriptionId !== null && subscriptionId !== void 0 ? subscriptionId : null);
732
+ }
733
+ catch { /* ignore */ }
734
+ }
735
+ },
736
+ // ── Cache control — Android parity (BillDog.kt:1074, :1612) ───────
737
+ /** Clear all SDK caches (paywall configs, customer info, products). */
738
+ async clearCache() {
739
+ if (native === null || native === void 0 ? void 0 : native.clearCache) {
740
+ try {
741
+ await native.clearCache();
742
+ }
743
+ catch { /* ignore */ }
744
+ }
745
+ },
746
+ /** Invalidate the cached customer info — next read triggers a refetch. */
747
+ async invalidateCustomerInfoCache() {
748
+ if (native === null || native === void 0 ? void 0 : native.invalidateCustomerInfoCache) {
749
+ try {
750
+ await native.invalidateCustomerInfoCache();
751
+ }
752
+ catch { /* ignore */ }
753
+ }
754
+ },
755
+ // ── User attributes — Android parity (BillDog.kt:1714, :1729) ─────
756
+ /** Set typed attributes on the current user (targeting + analytics). */
757
+ async setUserAttributes(attributes) {
758
+ if (native === null || native === void 0 ? void 0 : native.setUserAttributes) {
759
+ try {
760
+ await native.setUserAttributes(attributes);
761
+ }
762
+ catch { /* ignore */ }
763
+ }
764
+ // Also propagate to AnalyticsManager so events carry the same attrs.
765
+ try {
766
+ await Analytics_1.AnalyticsManager.getInstance().setSuperProperties(attributes);
767
+ }
768
+ catch { /* best-effort */ }
769
+ },
770
+ /** Get the current user attributes (snapshot). */
771
+ async getUserAttributes() {
772
+ var _a;
773
+ if (native === null || native === void 0 ? void 0 : native.getUserAttributes) {
774
+ try {
775
+ return (_a = (await native.getUserAttributes())) !== null && _a !== void 0 ? _a : {};
776
+ }
777
+ catch { /* ignore */ }
778
+ }
779
+ return {};
780
+ },
781
+ // ── External purchase observation — Android parity (BillDog.kt:1864–1878) ──
782
+ /** Notify BillDog that an externally-driven purchase has started. */
783
+ observePurchaseStart(productId) {
784
+ if (native === null || native === void 0 ? void 0 : native.observePurchaseStart) {
785
+ try {
786
+ native.observePurchaseStart(productId);
787
+ }
788
+ catch { /* ignore */ }
789
+ }
790
+ },
791
+ /** Notify BillDog that an externally-driven purchase succeeded. */
792
+ observePurchaseResult(productId, orderId) {
793
+ if (native === null || native === void 0 ? void 0 : native.observePurchaseResult) {
794
+ try {
795
+ native.observePurchaseResult(productId, orderId !== null && orderId !== void 0 ? orderId : null);
796
+ }
797
+ catch { /* ignore */ }
798
+ }
799
+ },
800
+ /** Notify BillDog that an externally-driven purchase failed. */
801
+ observePurchaseError(productId, error) {
802
+ if (native === null || native === void 0 ? void 0 : native.observePurchaseError) {
803
+ try {
804
+ native.observePurchaseError(productId, error);
805
+ }
806
+ catch { /* ignore */ }
807
+ }
808
+ },
809
+ // ── BillDogDelegate — Android parity (BillDog.kt:71) ──────────────
810
+ /**
811
+ * Set the active delegate. Pass `null` to detach. All delegate callbacks
812
+ * are optional; the SDK fires the ones that are defined.
813
+ */
814
+ setDelegate(delegate) {
815
+ activeDelegate = delegate;
816
+ },
817
+ /** Internal — emit a typed lifecycle event to the delegate (if any). */
818
+ _emitDelegate(event, ...args) {
819
+ const fn = activeDelegate === null || activeDelegate === void 0 ? void 0 : activeDelegate[event];
820
+ if (typeof fn === 'function') {
821
+ try {
822
+ fn(...args);
823
+ }
824
+ catch {
825
+ /* delegate errors must not propagate into SDK flow */
826
+ }
827
+ }
828
+ },
829
+ /**
830
+ * Evaluate what would happen if `register(placementId)` were called, without
831
+ * presenting a paywall. Returns one of `paywall`, `userSubscribed`,
832
+ * `noPaywall`, `holdout`, or `error`.
833
+ */
834
+ async getPresentationResult(placementId) {
835
+ var _a;
836
+ if (!BillDogConfiguration_1.BillDogConfiguration.isConfigured()) {
837
+ return { type: 'error', message: 'BillDog SDK not configured.' };
838
+ }
839
+ if (!(native === null || native === void 0 ? void 0 : native.getPresentationResult)) {
840
+ return { type: 'noPaywall', reason: 'Native placement bridge not wired' };
841
+ }
842
+ try {
843
+ const raw = await native.getPresentationResult(placementId);
844
+ if (raw && typeof raw.type === 'string')
845
+ return raw;
846
+ return { type: 'error', message: 'Malformed presentation result' };
847
+ }
848
+ catch (e) {
849
+ return { type: 'error', message: (_a = e === null || e === void 0 ? void 0 : e.message) !== null && _a !== void 0 ? _a : 'Presentation evaluation failed' };
850
+ }
851
+ },
852
+ /**
853
+ * Execute a server-side paywall tap action (Route B).
854
+ * Delegates to native SDK bridge `executeAction` if present; falls back to direct
855
+ * JavaScript fetch request to `execute-paywall-action` Edge Function if native is absent.
856
+ */
857
+ async executeAction(paywallId, componentId, actionType, idempotencyKey = null, metadata) {
858
+ if (native === null || native === void 0 ? void 0 : native.executeAction) {
859
+ try {
860
+ return await native.executeAction(paywallId, componentId, actionType, idempotencyKey, metadata);
861
+ }
862
+ catch (e) {
863
+ throw e;
864
+ }
865
+ }
866
+ try {
867
+ const endpoint = BillDogConfiguration_1.BillDogConfiguration.resolveEndpoint('execute-paywall-action');
868
+ const apiKey = BillDogConfiguration_1.BillDogConfiguration.getApiKey();
869
+ const appUserId = this.getAppUserId();
870
+ const body = {
871
+ paywall_id: paywallId,
872
+ component_id: componentId,
873
+ action_type: actionType,
874
+ idempotency_key: idempotencyKey,
875
+ };
876
+ if (appUserId) {
877
+ body.app_user_id = appUserId;
878
+ }
879
+ if (metadata) {
880
+ body.metadata = metadata;
881
+ }
882
+ const response = await fetch(endpoint, {
883
+ method: 'POST',
884
+ headers: {
885
+ 'Content-Type': 'application/json',
886
+ 'X-BillDog-API-Key': apiKey,
887
+ },
888
+ body: JSON.stringify(body),
889
+ });
890
+ if (!response.ok) {
891
+ const errorText = await response.text();
892
+ throw new Error(errorText || `HTTP ${response.status}`);
893
+ }
894
+ return await response.json();
895
+ }
896
+ catch (e) {
897
+ if (BillDogConfiguration_1.BillDogConfiguration.config.enableLogging) {
898
+ console.error('[BillDog] Failed to execute action:', e);
899
+ }
900
+ throw e;
901
+ }
902
+ },
903
+ };
904
+ /**
905
+ * Forward a single provider attribution id to the native `setAttribution`
906
+ * bridge. `null` is a documented no-op (native has no clear). Best-effort —
907
+ * native/bridge errors are swallowed so attribution never breaks a host app.
908
+ */
909
+ function setAttributionKey(key, id) {
910
+ if (!(native === null || native === void 0 ? void 0 : native.setAttribution) || id == null)
911
+ return;
912
+ try {
913
+ native.setAttribution({ [key]: id });
914
+ }
915
+ catch {
916
+ /* swallow — attribution is best-effort */
917
+ }
918
+ }