@whop/elements-react-native 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (339) hide show
  1. package/README.md +179 -0
  2. package/android/build.gradle +64 -0
  3. package/android/consumer-rules.pro +3 -0
  4. package/android/gradle.properties +5 -0
  5. package/android/src/main/java/com/whop/elements/WhopAddressSuggestionsModule.kt +102 -0
  6. package/android/src/main/java/com/whop/elements/WhopAuthSessionModule.kt +126 -0
  7. package/android/src/main/java/com/whop/elements/WhopElementsPackage.kt +39 -0
  8. package/android/src/main/java/com/whop/elements/WhopPayButtonManager.kt +74 -0
  9. package/android/src/main/java/com/whop/elements/WhopPayButtonPressEvent.kt +17 -0
  10. package/android/src/main/java/com/whop/elements/WhopPayButtonView.kt +178 -0
  11. package/android/src/main/java/com/whop/elements/WhopPlatformPayModule.kt +212 -0
  12. package/assets/whop-wordmark-dark.png +0 -0
  13. package/assets/whop-wordmark-dark@2x.png +0 -0
  14. package/assets/whop-wordmark-dark@3x.png +0 -0
  15. package/assets/whop-wordmark-light.png +0 -0
  16. package/assets/whop-wordmark-light@2x.png +0 -0
  17. package/assets/whop-wordmark-light@3x.png +0 -0
  18. package/ios/Package.swift +59 -0
  19. package/ios/Sources/ElementsReactNative/WhopAddressSuggestionsImpl.swift +189 -0
  20. package/ios/Sources/ElementsReactNative/WhopAuthSessionImpl.swift +106 -0
  21. package/ios/Sources/ElementsReactNative/WhopPayButtonImpl.swift +89 -0
  22. package/ios/Sources/ElementsReactNative/WhopPlatformPayImpl.swift +181 -0
  23. package/ios/generated/WhopAddressSuggestionsModule.h +11 -0
  24. package/ios/generated/WhopAddressSuggestionsModule.mm +46 -0
  25. package/ios/generated/WhopAuthSessionModule.h +11 -0
  26. package/ios/generated/WhopAuthSessionModule.mm +45 -0
  27. package/ios/generated/WhopElementsShims.h +35 -0
  28. package/ios/generated/WhopPayButtonComponentView.h +12 -0
  29. package/ios/generated/WhopPayButtonComponentView.mm +82 -0
  30. package/ios/generated/WhopPlatformPayModule.h +11 -0
  31. package/ios/generated/WhopPlatformPayModule.mm +51 -0
  32. package/lib/module/api/client.js +139 -0
  33. package/lib/module/api/client.js.map +1 -0
  34. package/lib/module/api/client.test.js +137 -0
  35. package/lib/module/api/client.test.js.map +1 -0
  36. package/lib/module/api/types.js +2 -0
  37. package/lib/module/api/types.js.map +1 -0
  38. package/lib/module/controller/actions.js +148 -0
  39. package/lib/module/controller/actions.js.map +1 -0
  40. package/lib/module/controller/actions.test.js +102 -0
  41. package/lib/module/controller/actions.test.js.map +1 -0
  42. package/lib/module/controller/store.js +158 -0
  43. package/lib/module/controller/store.js.map +1 -0
  44. package/lib/module/core/address/country-data.js +1370 -0
  45. package/lib/module/core/address/country-data.js.map +1 -0
  46. package/lib/module/core/address/country-name.js +38 -0
  47. package/lib/module/core/address/country-name.js.map +1 -0
  48. package/lib/module/core/address/country-names.generated.js +249 -0
  49. package/lib/module/core/address/country-names.generated.js.map +1 -0
  50. package/lib/module/core/address/engine.js +245 -0
  51. package/lib/module/core/address/engine.js.map +1 -0
  52. package/lib/module/core/address/engine.test.js +216 -0
  53. package/lib/module/core/address/engine.test.js.map +1 -0
  54. package/lib/module/core/address/form-state.js +409 -0
  55. package/lib/module/core/address/form-state.js.map +1 -0
  56. package/lib/module/core/address/form-state.test.js +516 -0
  57. package/lib/module/core/address/form-state.test.js.map +1 -0
  58. package/lib/module/core/address/places.js +36 -0
  59. package/lib/module/core/address/places.js.map +1 -0
  60. package/lib/module/core/address/required-coverage.test.js +57 -0
  61. package/lib/module/core/address/required-coverage.test.js.map +1 -0
  62. package/lib/module/core/address/suggest.js +102 -0
  63. package/lib/module/core/address/suggest.js.map +1 -0
  64. package/lib/module/core/address/suggest.test.js +156 -0
  65. package/lib/module/core/address/suggest.test.js.map +1 -0
  66. package/lib/module/core/address/use-suggestions.js +33 -0
  67. package/lib/module/core/address/use-suggestions.js.map +1 -0
  68. package/lib/module/core/payments/address-change.js +91 -0
  69. package/lib/module/core/payments/address-change.js.map +1 -0
  70. package/lib/module/core/payments/billing-merge.js +62 -0
  71. package/lib/module/core/payments/billing-merge.js.map +1 -0
  72. package/lib/module/core/payments/browser-info.js +42 -0
  73. package/lib/module/core/payments/browser-info.js.map +1 -0
  74. package/lib/module/core/payments/bt.js +151 -0
  75. package/lib/module/core/payments/bt.js.map +1 -0
  76. package/lib/module/core/payments/bt.test.js +23 -0
  77. package/lib/module/core/payments/bt.test.js.map +1 -0
  78. package/lib/module/core/payments/currency.js +37 -0
  79. package/lib/module/core/payments/currency.js.map +1 -0
  80. package/lib/module/core/payments/detail.js +159 -0
  81. package/lib/module/core/payments/detail.js.map +1 -0
  82. package/lib/module/core/payments/detail.test.js +225 -0
  83. package/lib/module/core/payments/detail.test.js.map +1 -0
  84. package/lib/module/core/payments/errors.js +115 -0
  85. package/lib/module/core/payments/errors.js.map +1 -0
  86. package/lib/module/core/payments/mint.js +89 -0
  87. package/lib/module/core/payments/mint.js.map +1 -0
  88. package/lib/module/core/payments/plan.js +131 -0
  89. package/lib/module/core/payments/plan.js.map +1 -0
  90. package/lib/module/core/payments/refusals.js +17 -0
  91. package/lib/module/core/payments/refusals.js.map +1 -0
  92. package/lib/module/core/payments/secure-fields.js +87 -0
  93. package/lib/module/core/payments/secure-fields.js.map +1 -0
  94. package/lib/module/core/payments/tax-id-catalog.js +616 -0
  95. package/lib/module/core/payments/tax-id-catalog.js.map +1 -0
  96. package/lib/module/core/payments/wallet-contact.js +42 -0
  97. package/lib/module/core/payments/wallet-contact.js.map +1 -0
  98. package/lib/module/core/payments/wallet-contact.test.js +77 -0
  99. package/lib/module/core/payments/wallet-contact.test.js.map +1 -0
  100. package/lib/module/elements/address.js +467 -0
  101. package/lib/module/elements/address.js.map +1 -0
  102. package/lib/module/elements/branding.js +114 -0
  103. package/lib/module/elements/branding.js.map +1 -0
  104. package/lib/module/elements/card-fields/context.js +254 -0
  105. package/lib/module/elements/card-fields/context.js.map +1 -0
  106. package/lib/module/elements/card-fields/fields.js +309 -0
  107. package/lib/module/elements/card-fields/fields.js.map +1 -0
  108. package/lib/module/elements/card-fields/index.js +30 -0
  109. package/lib/module/elements/card-fields/index.js.map +1 -0
  110. package/lib/module/elements/card.js +107 -0
  111. package/lib/module/elements/card.js.map +1 -0
  112. package/lib/module/elements/email.js +84 -0
  113. package/lib/module/elements/email.js.map +1 -0
  114. package/lib/module/elements/payment/declared-fields.js +186 -0
  115. package/lib/module/elements/payment/declared-fields.js.map +1 -0
  116. package/lib/module/elements/payment/index.js +448 -0
  117. package/lib/module/elements/payment/index.js.map +1 -0
  118. package/lib/module/elements/payment/wallet.js +132 -0
  119. package/lib/module/elements/payment/wallet.js.map +1 -0
  120. package/lib/module/elements/tax-id.js +100 -0
  121. package/lib/module/elements/tax-id.js.map +1 -0
  122. package/lib/module/i18n/catalogs.js +103 -0
  123. package/lib/module/i18n/catalogs.js.map +1 -0
  124. package/lib/module/i18n/index.js +45 -0
  125. package/lib/module/i18n/index.js.map +1 -0
  126. package/lib/module/index.js +27 -0
  127. package/lib/module/index.js.map +1 -0
  128. package/lib/module/namespace.js +174 -0
  129. package/lib/module/namespace.js.map +1 -0
  130. package/lib/module/native/index.js +128 -0
  131. package/lib/module/native/index.js.map +1 -0
  132. package/lib/module/package.json +1 -0
  133. package/lib/module/provider.js +56 -0
  134. package/lib/module/provider.js.map +1 -0
  135. package/lib/module/specs/NativeWhopAddressSuggestions.js +6 -0
  136. package/lib/module/specs/NativeWhopAddressSuggestions.js.map +1 -0
  137. package/lib/module/specs/NativeWhopAuthSession.js +10 -0
  138. package/lib/module/specs/NativeWhopAuthSession.js.map +1 -0
  139. package/lib/module/specs/NativeWhopPlatformPay.js +10 -0
  140. package/lib/module/specs/NativeWhopPlatformPay.js.map +1 -0
  141. package/lib/module/specs/WhopPayButtonNativeComponent.ts +22 -0
  142. package/lib/module/theme/appearance.js +85 -0
  143. package/lib/module/theme/appearance.js.map +1 -0
  144. package/lib/module/theme/appearance.test.js +124 -0
  145. package/lib/module/theme/appearance.test.js.map +1 -0
  146. package/lib/module/theme/provider.js +25 -0
  147. package/lib/module/theme/provider.js.map +1 -0
  148. package/lib/module/theme/resolve.js +69 -0
  149. package/lib/module/theme/resolve.js.map +1 -0
  150. package/lib/module/theme/scales.generated.js +419 -0
  151. package/lib/module/theme/scales.generated.js.map +1 -0
  152. package/lib/module/ui/element-frame.js +83 -0
  153. package/lib/module/ui/element-frame.js.map +1 -0
  154. package/lib/module/ui/payment-method-icon.js +69 -0
  155. package/lib/module/ui/payment-method-icon.js.map +1 -0
  156. package/lib/module/ui/primitives.js +266 -0
  157. package/lib/module/ui/primitives.js.map +1 -0
  158. package/lib/module/ui/select.js +281 -0
  159. package/lib/module/ui/select.js.map +1 -0
  160. package/lib/module/ui/suggestions.js +71 -0
  161. package/lib/module/ui/suggestions.js.map +1 -0
  162. package/lib/module/ui/whop-logo.js +42 -0
  163. package/lib/module/ui/whop-logo.js.map +1 -0
  164. package/lib/typescript/package.json +1 -0
  165. package/lib/typescript/src/api/client.d.ts +87 -0
  166. package/lib/typescript/src/api/client.d.ts.map +1 -0
  167. package/lib/typescript/src/api/types.d.ts +175 -0
  168. package/lib/typescript/src/api/types.d.ts.map +1 -0
  169. package/lib/typescript/src/controller/actions.d.ts +42 -0
  170. package/lib/typescript/src/controller/actions.d.ts.map +1 -0
  171. package/lib/typescript/src/controller/store.d.ts +90 -0
  172. package/lib/typescript/src/controller/store.d.ts.map +1 -0
  173. package/lib/typescript/src/core/address/country-data.d.ts +4 -0
  174. package/lib/typescript/src/core/address/country-data.d.ts.map +1 -0
  175. package/lib/typescript/src/core/address/country-name.d.ts +2 -0
  176. package/lib/typescript/src/core/address/country-name.d.ts.map +1 -0
  177. package/lib/typescript/src/core/address/country-names.generated.d.ts +2 -0
  178. package/lib/typescript/src/core/address/country-names.generated.d.ts.map +1 -0
  179. package/lib/typescript/src/core/address/engine.d.ts +97 -0
  180. package/lib/typescript/src/core/address/engine.d.ts.map +1 -0
  181. package/lib/typescript/src/core/address/form-state.d.ts +144 -0
  182. package/lib/typescript/src/core/address/form-state.d.ts.map +1 -0
  183. package/lib/typescript/src/core/address/places.d.ts +23 -0
  184. package/lib/typescript/src/core/address/places.d.ts.map +1 -0
  185. package/lib/typescript/src/core/address/suggest.d.ts +47 -0
  186. package/lib/typescript/src/core/address/suggest.d.ts.map +1 -0
  187. package/lib/typescript/src/core/address/use-suggestions.d.ts +3 -0
  188. package/lib/typescript/src/core/address/use-suggestions.d.ts.map +1 -0
  189. package/lib/typescript/src/core/payments/address-change.d.ts +52 -0
  190. package/lib/typescript/src/core/payments/address-change.d.ts.map +1 -0
  191. package/lib/typescript/src/core/payments/billing-merge.d.ts +39 -0
  192. package/lib/typescript/src/core/payments/billing-merge.d.ts.map +1 -0
  193. package/lib/typescript/src/core/payments/browser-info.d.ts +12 -0
  194. package/lib/typescript/src/core/payments/browser-info.d.ts.map +1 -0
  195. package/lib/typescript/src/core/payments/bt.d.ts +55 -0
  196. package/lib/typescript/src/core/payments/bt.d.ts.map +1 -0
  197. package/lib/typescript/src/core/payments/currency.d.ts +7 -0
  198. package/lib/typescript/src/core/payments/currency.d.ts.map +1 -0
  199. package/lib/typescript/src/core/payments/detail.d.ts +53 -0
  200. package/lib/typescript/src/core/payments/detail.d.ts.map +1 -0
  201. package/lib/typescript/src/core/payments/errors.d.ts +62 -0
  202. package/lib/typescript/src/core/payments/errors.d.ts.map +1 -0
  203. package/lib/typescript/src/core/payments/mint.d.ts +74 -0
  204. package/lib/typescript/src/core/payments/mint.d.ts.map +1 -0
  205. package/lib/typescript/src/core/payments/plan.d.ts +69 -0
  206. package/lib/typescript/src/core/payments/plan.d.ts.map +1 -0
  207. package/lib/typescript/src/core/payments/refusals.d.ts +12 -0
  208. package/lib/typescript/src/core/payments/refusals.d.ts.map +1 -0
  209. package/lib/typescript/src/core/payments/secure-fields.d.ts +33 -0
  210. package/lib/typescript/src/core/payments/secure-fields.d.ts.map +1 -0
  211. package/lib/typescript/src/core/payments/tax-id-catalog.d.ts +481 -0
  212. package/lib/typescript/src/core/payments/tax-id-catalog.d.ts.map +1 -0
  213. package/lib/typescript/src/core/payments/wallet-contact.d.ts +40 -0
  214. package/lib/typescript/src/core/payments/wallet-contact.d.ts.map +1 -0
  215. package/lib/typescript/src/elements/address.d.ts +55 -0
  216. package/lib/typescript/src/elements/address.d.ts.map +1 -0
  217. package/lib/typescript/src/elements/branding.d.ts +18 -0
  218. package/lib/typescript/src/elements/branding.d.ts.map +1 -0
  219. package/lib/typescript/src/elements/card-fields/context.d.ts +67 -0
  220. package/lib/typescript/src/elements/card-fields/context.d.ts.map +1 -0
  221. package/lib/typescript/src/elements/card-fields/fields.d.ts +15 -0
  222. package/lib/typescript/src/elements/card-fields/fields.d.ts.map +1 -0
  223. package/lib/typescript/src/elements/card-fields/index.d.ts +21 -0
  224. package/lib/typescript/src/elements/card-fields/index.d.ts.map +1 -0
  225. package/lib/typescript/src/elements/card.d.ts +21 -0
  226. package/lib/typescript/src/elements/card.d.ts.map +1 -0
  227. package/lib/typescript/src/elements/email.d.ts +31 -0
  228. package/lib/typescript/src/elements/email.d.ts.map +1 -0
  229. package/lib/typescript/src/elements/payment/declared-fields.d.ts +43 -0
  230. package/lib/typescript/src/elements/payment/declared-fields.d.ts.map +1 -0
  231. package/lib/typescript/src/elements/payment/index.d.ts +37 -0
  232. package/lib/typescript/src/elements/payment/index.d.ts.map +1 -0
  233. package/lib/typescript/src/elements/payment/wallet.d.ts +39 -0
  234. package/lib/typescript/src/elements/payment/wallet.d.ts.map +1 -0
  235. package/lib/typescript/src/elements/tax-id.d.ts +41 -0
  236. package/lib/typescript/src/elements/tax-id.d.ts.map +1 -0
  237. package/lib/typescript/src/i18n/catalogs.d.ts +7 -0
  238. package/lib/typescript/src/i18n/catalogs.d.ts.map +1 -0
  239. package/lib/typescript/src/i18n/index.d.ts +17 -0
  240. package/lib/typescript/src/i18n/index.d.ts.map +1 -0
  241. package/lib/typescript/src/index.d.ts +42 -0
  242. package/lib/typescript/src/index.d.ts.map +1 -0
  243. package/lib/typescript/src/namespace.d.ts +36 -0
  244. package/lib/typescript/src/namespace.d.ts.map +1 -0
  245. package/lib/typescript/src/native/index.d.ts +62 -0
  246. package/lib/typescript/src/native/index.d.ts.map +1 -0
  247. package/lib/typescript/src/provider.d.ts +37 -0
  248. package/lib/typescript/src/provider.d.ts.map +1 -0
  249. package/lib/typescript/src/specs/NativeWhopAddressSuggestions.d.ts +13 -0
  250. package/lib/typescript/src/specs/NativeWhopAddressSuggestions.d.ts.map +1 -0
  251. package/lib/typescript/src/specs/NativeWhopAuthSession.d.ts +20 -0
  252. package/lib/typescript/src/specs/NativeWhopAuthSession.d.ts.map +1 -0
  253. package/lib/typescript/src/specs/NativeWhopPlatformPay.d.ts +24 -0
  254. package/lib/typescript/src/specs/NativeWhopPlatformPay.d.ts.map +1 -0
  255. package/lib/typescript/src/specs/WhopPayButtonNativeComponent.d.ts +21 -0
  256. package/lib/typescript/src/specs/WhopPayButtonNativeComponent.d.ts.map +1 -0
  257. package/lib/typescript/src/theme/appearance.d.ts +71 -0
  258. package/lib/typescript/src/theme/appearance.d.ts.map +1 -0
  259. package/lib/typescript/src/theme/provider.d.ts +11 -0
  260. package/lib/typescript/src/theme/provider.d.ts.map +1 -0
  261. package/lib/typescript/src/theme/resolve.d.ts +19 -0
  262. package/lib/typescript/src/theme/resolve.d.ts.map +1 -0
  263. package/lib/typescript/src/theme/scales.generated.d.ts +18 -0
  264. package/lib/typescript/src/theme/scales.generated.d.ts.map +1 -0
  265. package/lib/typescript/src/ui/element-frame.d.ts +32 -0
  266. package/lib/typescript/src/ui/element-frame.d.ts.map +1 -0
  267. package/lib/typescript/src/ui/payment-method-icon.d.ts +21 -0
  268. package/lib/typescript/src/ui/payment-method-icon.d.ts.map +1 -0
  269. package/lib/typescript/src/ui/primitives.d.ts +94 -0
  270. package/lib/typescript/src/ui/primitives.d.ts.map +1 -0
  271. package/lib/typescript/src/ui/select.d.ts +25 -0
  272. package/lib/typescript/src/ui/select.d.ts.map +1 -0
  273. package/lib/typescript/src/ui/suggestions.d.ts +15 -0
  274. package/lib/typescript/src/ui/suggestions.d.ts.map +1 -0
  275. package/lib/typescript/src/ui/whop-logo.d.ts +4 -0
  276. package/lib/typescript/src/ui/whop-logo.d.ts.map +1 -0
  277. package/package.json +121 -0
  278. package/scripts/check-swift.sh +27 -0
  279. package/scripts/codegen-shims.mjs +409 -0
  280. package/scripts/gen-country-names.mjs +58 -0
  281. package/scripts/gen-theme.mjs +124 -0
  282. package/scripts/gen-wordmark.mjs +68 -0
  283. package/scripts/mirror.mjs +112 -0
  284. package/src/api/client.ts +202 -0
  285. package/src/api/types.ts +166 -0
  286. package/src/controller/actions.ts +197 -0
  287. package/src/controller/store.ts +201 -0
  288. package/src/core/address/country-data.ts +927 -0
  289. package/src/core/address/country-name.ts +36 -0
  290. package/src/core/address/country-names.generated.ts +246 -0
  291. package/src/core/address/engine.ts +349 -0
  292. package/src/core/address/form-state.ts +479 -0
  293. package/src/core/address/places.ts +39 -0
  294. package/src/core/address/suggest.ts +153 -0
  295. package/src/core/address/use-suggestions.ts +37 -0
  296. package/src/core/payments/address-change.ts +121 -0
  297. package/src/core/payments/billing-merge.ts +91 -0
  298. package/src/core/payments/browser-info.ts +43 -0
  299. package/src/core/payments/bt.ts +176 -0
  300. package/src/core/payments/currency.ts +54 -0
  301. package/src/core/payments/detail.ts +204 -0
  302. package/src/core/payments/errors.ts +171 -0
  303. package/src/core/payments/mint.ts +130 -0
  304. package/src/core/payments/plan.ts +198 -0
  305. package/src/core/payments/refusals.ts +24 -0
  306. package/src/core/payments/secure-fields.ts +85 -0
  307. package/src/core/payments/tax-id-catalog.ts +320 -0
  308. package/src/core/payments/wallet-contact.ts +56 -0
  309. package/src/elements/address.tsx +570 -0
  310. package/src/elements/branding.tsx +87 -0
  311. package/src/elements/card-fields/context.tsx +310 -0
  312. package/src/elements/card-fields/fields.tsx +281 -0
  313. package/src/elements/card-fields/index.tsx +37 -0
  314. package/src/elements/card.tsx +101 -0
  315. package/src/elements/email.tsx +100 -0
  316. package/src/elements/payment/declared-fields.tsx +238 -0
  317. package/src/elements/payment/index.tsx +497 -0
  318. package/src/elements/payment/wallet.tsx +155 -0
  319. package/src/elements/tax-id.tsx +143 -0
  320. package/src/i18n/catalogs.ts +100 -0
  321. package/src/i18n/index.tsx +46 -0
  322. package/src/index.ts +68 -0
  323. package/src/namespace.tsx +231 -0
  324. package/src/native/index.ts +173 -0
  325. package/src/provider.tsx +76 -0
  326. package/src/specs/NativeWhopAddressSuggestions.ts +14 -0
  327. package/src/specs/NativeWhopAuthSession.ts +21 -0
  328. package/src/specs/NativeWhopPlatformPay.ts +25 -0
  329. package/src/specs/WhopPayButtonNativeComponent.ts +22 -0
  330. package/src/theme/appearance.ts +150 -0
  331. package/src/theme/provider.tsx +28 -0
  332. package/src/theme/resolve.ts +68 -0
  333. package/src/theme/scales.generated.ts +427 -0
  334. package/src/ui/element-frame.tsx +94 -0
  335. package/src/ui/payment-method-icon.tsx +55 -0
  336. package/src/ui/primitives.tsx +269 -0
  337. package/src/ui/select.tsx +255 -0
  338. package/src/ui/suggestions.tsx +69 -0
  339. package/src/ui/whop-logo.tsx +37 -0
@@ -0,0 +1,51 @@
1
+ // GENERATED by scripts/codegen-shims.mjs — do not edit, do not commit.
2
+ // Source of truth: src/specs/. Implementations are Swift, in ios/Sources/WhopElements.
3
+
4
+ #import "WhopPlatformPayModule.h"
5
+ #import "WhopElementsShims.h"
6
+
7
+ @implementation WhopPlatformPayModule {
8
+ WhopPlatformPayImpl *_impl;
9
+ }
10
+
11
+ // The JS name, explicitly: bare RCT_EXPORT_MODULE() registers under the CLASS name
12
+ // ("WhopPlatformPayModule"), and TurboModuleRegistry then cannot find "WhopPlatformPay".
13
+ RCT_EXPORT_MODULE(WhopPlatformPay)
14
+
15
+ - (instancetype)init
16
+ {
17
+ if (self = [super init]) {
18
+ _impl = [WhopPlatformPayImpl new];
19
+ }
20
+ return self;
21
+ }
22
+
23
+ - (std::shared_ptr<facebook::react::TurboModule>)getTurboModule:
24
+ (const facebook::react::ObjCTurboModule::InitParams &)params
25
+ {
26
+ return std::make_shared<facebook::react::NativeWhopPlatformPaySpecJSI>(params);
27
+ }
28
+
29
+ - (NSString *)capability
30
+ {
31
+ return [_impl capability];
32
+ }
33
+
34
+ - (void)canPay:(NSString *)configJson resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject
35
+ {
36
+ [_impl canPay:configJson resolve:^(id _Nullable value) { resolve(value); }
37
+ reject:^(NSString *code, NSString *message) { reject(code, message, nil); }];
38
+ }
39
+
40
+ - (void)present:(NSString *)requestJson resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject
41
+ {
42
+ [_impl present:requestJson resolve:^(id _Nullable value) { resolve(value); }
43
+ reject:^(NSString *code, NSString *message) { reject(code, message, nil); }];
44
+ }
45
+
46
+ - (void)complete:(BOOL)success
47
+ {
48
+ [_impl complete:success];
49
+ }
50
+
51
+ @end
@@ -0,0 +1,139 @@
1
+ "use strict";
2
+
3
+ /**
4
+ * The API origin is an ENUM over two Whop-owned hosts, never a consumer-supplied string.
5
+ *
6
+ * A consumer-settable origin would let the embedding app point a payment surface at a host it
7
+ * controls and read everything a buyer types into it. The web elements hold the same line
8
+ * (`elements-framework/src/builder/api-base.ts`); this is that rule on React Native.
9
+ */
10
+ export const API_BASES = {
11
+ production: 'https://api.whop.com',
12
+ sandbox: 'https://api.sandbox.whop.com'
13
+ };
14
+ /**
15
+ * Pinned so a server-side schema roll cannot change what a shipped app parses.
16
+ *
17
+ * Must be a REAL released version: the API rejects an unknown date outright, before it even looks
18
+ * at the request. The published list is `Api::Versioning::RELEASED` in
19
+ * backend/lib/api/versioning.rb — bump this to a date from there, never to today's date.
20
+ */
21
+ const API_VERSION_DATE = '2026-08-25';
22
+ export class WhopError extends Error {
23
+ /** Alias of `status`; the ported payments error helpers read this name. */
24
+
25
+ constructor(message, status, code, body) {
26
+ super(message);
27
+ this.name = 'WhopError';
28
+ this.status = status;
29
+ this.statusCode = status;
30
+ this.code = code;
31
+ this.body = body;
32
+ }
33
+ }
34
+ const RETRYABLE = new Set([408, 429, 500, 502, 503, 504]);
35
+ export class WhopClient {
36
+ constructor(options = {}) {
37
+ this.options = options;
38
+ this.baseUrl = API_BASES[options.environment ?? 'production'];
39
+ this.doFetch = options.fetch ?? globalThis.fetch;
40
+ }
41
+ async request(method, path, opts = {}) {
42
+ const url = new URL(`/api/v1${path}`, this.baseUrl);
43
+ for (const [key, value] of Object.entries(opts.query ?? {})) {
44
+ if (value !== undefined) url.searchParams.set(key, String(value));
45
+ }
46
+ const token = opts.token !== undefined ? opts.token : await this.options.getToken?.();
47
+ const sessionKey = this.options.getSessionKey?.();
48
+ const headers = {
49
+ accept: 'application/json',
50
+ 'api-version-date': API_VERSION_DATE
51
+ };
52
+ if (opts.body !== undefined) headers['content-type'] = 'application/json';
53
+ if (token) headers.authorization = `Bearer ${token}`;
54
+ if (sessionKey) headers['x-ssk'] = sessionKey;
55
+ const maxRetries = opts.maxRetries ?? 2;
56
+ let lastError;
57
+ for (let attempt = 0; attempt <= maxRetries; attempt += 1) {
58
+ let response;
59
+ try {
60
+ response = await this.doFetch(url.toString(), {
61
+ method,
62
+ headers,
63
+ body: opts.body === undefined ? undefined : JSON.stringify(opts.body),
64
+ signal: opts.signal
65
+ });
66
+ } catch (err) {
67
+ lastError = new WhopError(err instanceof Error ? err.message : 'the network request failed', 0, 'NETWORK_UNAVAILABLE');
68
+ if (attempt === maxRetries) throw lastError;
69
+ await backoff(attempt);
70
+ continue;
71
+ }
72
+ if (response.ok) {
73
+ if (response.status === 204) return undefined;
74
+ return await response.json();
75
+ }
76
+ const body = await response.json().catch(() => undefined);
77
+ const error = new WhopError(errorMessage(body, response.status), response.status, errorCode(body), body);
78
+ if (!RETRYABLE.has(response.status) || attempt === maxRetries) throw error;
79
+ lastError = error;
80
+ await backoff(attempt);
81
+ }
82
+ throw lastError instanceof Error ? lastError : new WhopError('the request failed', 0);
83
+ }
84
+ plans = {
85
+ retrieve: id => this.request('GET', `/plans/${encodeURIComponent(id)}`)
86
+ };
87
+ paymentMethodTypes = {
88
+ list: query => this.request('GET', '/payment_method_types', {
89
+ query
90
+ }),
91
+ retrieve: (type, query) => this.request('GET', `/payment_method_types/${encodeURIComponent(type)}`, {
92
+ query
93
+ }),
94
+ /** Authorizes a Basis Theory session against the nonce-derived card-assembly container. */
95
+ createSession: (type, body) => this.request('POST', `/payment_method_types/${encodeURIComponent(type)}/session`, {
96
+ body
97
+ })
98
+ };
99
+ confirmationTokens = {
100
+ create: body => this.request('POST', '/confirmation_tokens', {
101
+ body,
102
+ maxRetries: 0
103
+ }),
104
+ retrieve: id => this.request('GET', `/confirmation_tokens/${encodeURIComponent(id)}`)
105
+ };
106
+ payments = {
107
+ /** The client secret both identifies and authorizes, so no payment id is needed. */
108
+ retrieveBySecret: clientSecret => this.request('GET', `/payments/${encodeURIComponent(paymentTagFrom(clientSecret))}`, {
109
+ query: {
110
+ client_secret: clientSecret
111
+ }
112
+ }),
113
+ updateBySecret: (clientSecret, body) => this.request('PATCH', `/payments/${encodeURIComponent(paymentTagFrom(clientSecret))}`, {
114
+ query: {
115
+ client_secret: clientSecret
116
+ },
117
+ body,
118
+ maxRetries: 0
119
+ })
120
+ };
121
+ }
122
+
123
+ /** `pay_<tag>_secret_v<n>` — the tag is embedded, which is why the secret is the whole reference. */
124
+ export function paymentTagFrom(clientSecret) {
125
+ const marker = clientSecret.indexOf('_secret_');
126
+ return marker === -1 ? clientSecret : clientSecret.slice(0, marker);
127
+ }
128
+ function errorMessage(body, status) {
129
+ const detail = body ?? undefined;
130
+ return detail?.error?.message ?? detail?.message ?? `the request failed with status ${status}`;
131
+ }
132
+ function errorCode(body) {
133
+ const detail = body ?? undefined;
134
+ return detail?.error?.code ?? detail?.error?.type;
135
+ }
136
+ function backoff(attempt) {
137
+ return new Promise(resolve => setTimeout(resolve, 2 ** attempt * 250));
138
+ }
139
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["API_BASES","production","sandbox","API_VERSION_DATE","WhopError","Error","constructor","message","status","code","body","name","statusCode","RETRYABLE","Set","WhopClient","options","baseUrl","environment","doFetch","fetch","globalThis","request","method","path","opts","url","URL","key","value","Object","entries","query","undefined","searchParams","set","String","token","getToken","sessionKey","getSessionKey","headers","accept","authorization","maxRetries","lastError","attempt","response","toString","JSON","stringify","signal","err","backoff","ok","json","catch","error","errorMessage","errorCode","has","plans","retrieve","id","encodeURIComponent","paymentMethodTypes","list","type","createSession","confirmationTokens","create","payments","retrieveBySecret","clientSecret","paymentTagFrom","client_secret","updateBySecret","marker","indexOf","slice","detail","Promise","resolve","setTimeout"],"sourceRoot":"../../../src","sources":["api/client.ts"],"mappings":"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","ignoreList":[]}
@@ -0,0 +1,137 @@
1
+ "use strict";
2
+
3
+ import { describe, expect, it } from 'vitest';
4
+ import { API_BASES, paymentTagFrom, WhopClient, WhopError } from "./client.js";
5
+ describe('API_BASES', () => {
6
+ // The origin is an enum over two Whop-owned hosts; a consumer-settable one would let an
7
+ // embedding app read everything a buyer types.
8
+ it('is a closed set of Whop origins', () => {
9
+ expect(Object.keys(API_BASES).sort()).toEqual(['production', 'sandbox']);
10
+ for (const origin of Object.values(API_BASES)) {
11
+ expect(origin).toMatch(/^https:\/\/[a-z.]*whop\.com$/);
12
+ }
13
+ });
14
+ });
15
+ describe('paymentTagFrom', () => {
16
+ it('reads the tag embedded in the client secret', () => {
17
+ expect(paymentTagFrom('pay_abc123_secret_v1')).toBe('pay_abc123');
18
+ });
19
+ it('passes a bare id through', () => {
20
+ expect(paymentTagFrom('pay_abc123')).toBe('pay_abc123');
21
+ });
22
+ });
23
+ describe('WhopClient', () => {
24
+ function stub(handler) {
25
+ const calls = [];
26
+ const client = new WhopClient({
27
+ environment: 'sandbox',
28
+ getToken: () => 'tok_buyer',
29
+ fetch: async (url, init) => {
30
+ calls.push({
31
+ url,
32
+ init
33
+ });
34
+ return handler(url, init);
35
+ }
36
+ });
37
+ return {
38
+ client,
39
+ calls
40
+ };
41
+ }
42
+ const ok = body => new Response(JSON.stringify(body), {
43
+ status: 200,
44
+ headers: {
45
+ 'content-type': 'application/json'
46
+ }
47
+ });
48
+
49
+ // The pinned value must be a REAL entry in Api::Versioning::RELEASED
50
+ // (backend/lib/api/versioning.rb). The API rejects an unknown date before it looks at anything
51
+ // else, so an invented one 400s every request the SDK makes.
52
+ it('pins a released api version and forwards the resolved token', async () => {
53
+ const {
54
+ client,
55
+ calls
56
+ } = stub(() => ok({
57
+ id: 'plan_1',
58
+ object: 'plan',
59
+ currency: 'usd'
60
+ }));
61
+ await client.plans.retrieve('plan_1');
62
+ const headers = calls[0].init.headers;
63
+ expect(calls[0].url).toBe('https://api.sandbox.whop.com/api/v1/plans/plan_1');
64
+ expect(headers['api-version-date']).toBe('2026-08-25');
65
+ expect(headers.authorization).toBe('Bearer tok_buyer');
66
+ // A date shape, never something like "latest" or a build timestamp.
67
+ expect(headers['api-version-date']).toMatch(/^\d{4}-\d{2}-\d{2}(-\d+)?$/);
68
+ });
69
+ it('drops undefined query values instead of sending the string "undefined"', async () => {
70
+ const {
71
+ client,
72
+ calls
73
+ } = stub(() => ok({
74
+ data: [],
75
+ page_info: {}
76
+ }));
77
+ await client.paymentMethodTypes.list({
78
+ account_id: 'biz_1',
79
+ currency: 'usd',
80
+ amount: undefined
81
+ });
82
+ expect(calls[0].url).toContain('account_id=biz_1');
83
+ expect(calls[0].url).toContain('currency=usd');
84
+ expect(calls[0].url).not.toContain('amount');
85
+ });
86
+ it('surfaces the API error message and code', async () => {
87
+ const {
88
+ client
89
+ } = stub(() => new Response(JSON.stringify({
90
+ error: {
91
+ message: 'plan not found',
92
+ code: 'not_found'
93
+ }
94
+ }), {
95
+ status: 404
96
+ }));
97
+ await expect(client.plans.retrieve('plan_missing')).rejects.toMatchObject({
98
+ message: 'plan not found',
99
+ code: 'not_found',
100
+ status: 404,
101
+ statusCode: 404
102
+ });
103
+ });
104
+ it('never retries a confirmation-token create', async () => {
105
+ let attempts = 0;
106
+ const {
107
+ client
108
+ } = stub(() => {
109
+ attempts += 1;
110
+ return new Response(JSON.stringify({
111
+ error: {
112
+ message: 'boom'
113
+ }
114
+ }), {
115
+ status: 500
116
+ });
117
+ });
118
+ await expect(client.confirmationTokens.create({
119
+ account_id: 'biz_1',
120
+ payment_method: {
121
+ category: 'card'
122
+ },
123
+ billing_details: {}
124
+ })).rejects.toBeInstanceOf(WhopError);
125
+ expect(attempts).toBe(1);
126
+ });
127
+ it('reports an unreachable network as a coded failure', async () => {
128
+ const client = new WhopClient({
129
+ environment: 'sandbox',
130
+ fetch: () => Promise.reject(new Error('offline'))
131
+ });
132
+ await expect(client.plans.retrieve('plan_1')).rejects.toMatchObject({
133
+ code: 'NETWORK_UNAVAILABLE'
134
+ });
135
+ });
136
+ });
137
+ //# sourceMappingURL=client.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["describe","expect","it","API_BASES","paymentTagFrom","WhopClient","WhopError","Object","keys","sort","toEqual","origin","values","toMatch","toBe","stub","handler","calls","client","environment","getToken","fetch","url","init","push","ok","body","Response","JSON","stringify","status","headers","id","object","currency","plans","retrieve","authorization","data","page_info","paymentMethodTypes","list","account_id","amount","undefined","toContain","not","error","message","code","rejects","toMatchObject","statusCode","attempts","confirmationTokens","create","payment_method","category","billing_details","toBeInstanceOf","Promise","reject","Error"],"sourceRoot":"../../../src","sources":["api/client.test.ts"],"mappings":"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","ignoreList":[]}
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":[],"sourceRoot":"../../../src","sources":["api/types.ts"],"mappings":"","ignoreList":[]}
@@ -0,0 +1,148 @@
1
+ "use strict";
2
+
3
+ import { mergeBillingWithCollected } from "../core/payments/billing-merge.js";
4
+ import { BrandingRequiredError } from "../core/payments/errors.js";
5
+ import { PaymentsRefusalError } from "../core/payments/refusals.js";
6
+ import { mintConfirmationToken, validateBillingEmail } from "../core/payments/mint.js";
7
+ import { WhopAuthSession } from "../native/index.js";
8
+ /**
9
+ * The one mint. Resolves the live collection surface, merges the billing block underneath any
10
+ * explicit input, and posts `POST /confirmation_tokens`.
11
+ */
12
+ export async function createConfirmationToken(store, input = {}) {
13
+ const state = store.getSnapshot();
14
+ if (state.confirmInFlight) {
15
+ throw new PaymentsRefusalError('CONFIRMATION_IN_FLIGHT', 'A confirmation token is already being created for this handle.');
16
+ }
17
+ // Whop is the merchant of record on these sales, so the buyer has to be told so on the screen
18
+ // where they pay. The web element cannot demand this of already-shipped integrations; a first
19
+ // release can, and does.
20
+ if (!state.brandingMounted) {
21
+ throw new BrandingRequiredError('BRANDING_NOT_MOUNTED', 'Mount <BrandingElement /> alongside your payment surface — it carries the merchant-of-record notice.');
22
+ }
23
+ if (!state.charge.configured) {
24
+ throw new PaymentsRefusalError('CHARGE_CONFIG_MISSING', 'This handle has no charge config — pass a plan or currency and amount.');
25
+ }
26
+ const surface = store.liveSurface();
27
+ if (!surface) {
28
+ throw new PaymentsRefusalError('NO_COLLECTION_SURFACE', 'No collection surface is mounted — render <PaymentElement />, <CardElement />, or <CardFields>.');
29
+ }
30
+ store.patch({
31
+ confirmInFlight: true
32
+ });
33
+ try {
34
+ const seeded = {
35
+ ...input.billingDetails,
36
+ email: input.billingDetails?.email ?? state.buyerEmail
37
+ };
38
+ const collected = await surface.collect({
39
+ billingDetails: seeded
40
+ });
41
+
42
+ // Re-read AFTER collect: card and wallet collection take seconds, and a buyer editing their
43
+ // address or email meanwhile must have the live values minted, not the pre-collect snapshot.
44
+ const settled = store.getSnapshot();
45
+ const email = input.billingDetails?.email ?? settled.buyerEmail ?? seeded.email;
46
+ const billing = mergeBillingWithCollected({
47
+ ...collected.billingDetails,
48
+ ...input.billingDetails,
49
+ email: email || collected.billingDetails.email
50
+ }, settled.addressLive ? settled.addressCollected : undefined);
51
+ return await mintConfirmationToken(store.client, {
52
+ accountId: settled.accountId,
53
+ returnUrl: settled.returnUrl,
54
+ setupFutureUsage: settled.charge.configured ? settled.charge.setupFutureUsage : undefined
55
+ }, collected.paymentMethod, validateBillingEmail(billing), {
56
+ ...collected.billingExtra,
57
+ ...input.billingExtra
58
+ });
59
+ } finally {
60
+ store.patch({
61
+ confirmInFlight: false
62
+ });
63
+ }
64
+ }
65
+ const RESTING = new Set(['succeeded', 'failed', 'canceled', 'cancelled', 'requires_payment_method']);
66
+
67
+ /**
68
+ * Completes a confirmed payment's pending step.
69
+ *
70
+ * The redirect leg opens the system browser and then **polls the payment to rest**. Polling is the
71
+ * authority rather than a callback because the API refuses anything but https or loopback for a
72
+ * return URL (`PaymentsApi::ValidateReturnUrl`), so a custom-scheme deep link back into the app is
73
+ * not available. Dismissing the browser therefore returns the payment's current status, which may
74
+ * still be pending — the same contract the web action documents.
75
+ */
76
+ export async function handleNextAction(store, input) {
77
+ // One at a time, like the mint. Two overlapping calls each open a system browser and each run
78
+ // their own poll, and whichever finishes first calls dismiss() — closing the OTHER buyer-facing
79
+ // challenge mid-flow and orphaning its presentation. A double-tapped submit is enough to do it.
80
+ if (store.getSnapshot().nextActionInFlight) {
81
+ throw new PaymentsRefusalError('NEXT_ACTION_IN_FLIGHT', 'A payment step is already being handled for this handle.');
82
+ }
83
+ store.patch({
84
+ nextActionInFlight: true
85
+ });
86
+ try {
87
+ return await runNextAction(store, input);
88
+ } finally {
89
+ store.patch({
90
+ nextActionInFlight: false
91
+ });
92
+ }
93
+ }
94
+ async function runNextAction(store, input) {
95
+ const pollIntervalMs = input.pollIntervalMs ?? 2500;
96
+ const timeoutMs = input.timeoutMs ?? 300_000;
97
+ if (input.returnUrl) {
98
+ // A failed update rejects BEFORE any step runs, so the buyer is never sent somewhere the
99
+ // payment does not know about.
100
+ await store.client.payments.updateBySecret(input.clientSecret, {
101
+ return_url: input.returnUrl
102
+ });
103
+ }
104
+ let payment = await store.client.payments.retrieveBySecret(input.clientSecret);
105
+ const url = payment.next_action?.redirect?.url;
106
+ if (!payment.next_action || !url) {
107
+ return {
108
+ status: payment.status,
109
+ redirected: false,
110
+ lastPaymentError: payment.last_payment_error ?? null
111
+ };
112
+ }
113
+
114
+ // A mutable box rather than a bare `let`: the assignment happens inside a callback, which control
115
+ // flow analysis does not see, so a plain binding narrows to `null` at every read below.
116
+ const presented = {
117
+ error: null
118
+ };
119
+ const presentation = WhopAuthSession.present(url).catch(error => {
120
+ presented.error = error instanceof Error ? error : new Error(String(error));
121
+ });
122
+ const deadline = Date.now() + timeoutMs;
123
+ try {
124
+ while (Date.now() < deadline) {
125
+ await delay(pollIntervalMs);
126
+ // The buyer cannot be completing a step that never opened. Without this the poll runs the
127
+ // full timeout and then reports a redirect that never happened.
128
+ if (presented.error) break;
129
+ payment = await store.client.payments.retrieveBySecret(input.clientSecret).catch(() => payment);
130
+ if (RESTING.has(payment.status) || !payment.next_action) break;
131
+ }
132
+ } finally {
133
+ WhopAuthSession.dismiss();
134
+ await presentation;
135
+ }
136
+ if (presented.error) {
137
+ throw new PaymentsRefusalError('NEXT_ACTION_PRESENTATION_FAILED', `The payment step could not be opened: ${presented.error.message}`);
138
+ }
139
+ return {
140
+ status: payment.status,
141
+ redirected: true,
142
+ lastPaymentError: payment.last_payment_error ?? null
143
+ };
144
+ }
145
+ function delay(ms) {
146
+ return new Promise(resolve => setTimeout(resolve, ms));
147
+ }
148
+ //# sourceMappingURL=actions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["mergeBillingWithCollected","BrandingRequiredError","PaymentsRefusalError","mintConfirmationToken","validateBillingEmail","WhopAuthSession","createConfirmationToken","store","input","state","getSnapshot","confirmInFlight","brandingMounted","charge","configured","surface","liveSurface","patch","seeded","billingDetails","email","buyerEmail","collected","collect","settled","billing","addressLive","addressCollected","undefined","client","accountId","returnUrl","setupFutureUsage","paymentMethod","billingExtra","RESTING","Set","handleNextAction","nextActionInFlight","runNextAction","pollIntervalMs","timeoutMs","payments","updateBySecret","clientSecret","return_url","payment","retrieveBySecret","url","next_action","redirect","status","redirected","lastPaymentError","last_payment_error","presented","error","presentation","present","catch","Error","String","deadline","Date","now","delay","has","dismiss","message","ms","Promise","resolve","setTimeout"],"sourceRoot":"../../../src","sources":["controller/actions.ts"],"mappings":"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","ignoreList":[]}
@@ -0,0 +1,102 @@
1
+ "use strict";
2
+
3
+ import { describe, expect, it, vi } from 'vitest';
4
+
5
+ // `../native` reaches react-native, whose Flow source vitest cannot parse. The redirect leg is not
6
+ // what these tests exercise: they are about the in-flight guard around it.
7
+ vi.mock('../native', () => ({
8
+ WhopAuthSession: {
9
+ present: vi.fn(async () => null),
10
+ dismiss: vi.fn()
11
+ },
12
+ WhopPlatformPay: {
13
+ capability: vi.fn(() => 'none')
14
+ },
15
+ WALLET_TYPE_FOR_PLATFORM: 'apple_pay'
16
+ }));
17
+ import { PaymentsRefusalError } from "../core/payments/refusals.js";
18
+ import { handleNextAction } from "./actions.js";
19
+ /**
20
+ * The store as `handleNextAction` uses it: a state bag it reads and patches, and a client whose
21
+ * payments resource it polls. Building the real one would open a network client and resolve a
22
+ * charge, neither of which this behaviour depends on.
23
+ */
24
+ function fakeStore(payment) {
25
+ const state = {
26
+ nextActionInFlight: false
27
+ };
28
+ let retrieves = 0;
29
+ return {
30
+ store: {
31
+ getSnapshot: () => state,
32
+ patch: next => Object.assign(state, next),
33
+ client: {
34
+ payments: {
35
+ updateBySecret: vi.fn(async () => payment),
36
+ retrieveBySecret: vi.fn(async () => {
37
+ retrieves += 1;
38
+ return payment;
39
+ })
40
+ }
41
+ }
42
+ },
43
+ state,
44
+ retrieves: () => retrieves
45
+ };
46
+ }
47
+ describe('handleNextAction', () => {
48
+ it('returns without redirecting when the payment has no next action', async () => {
49
+ const {
50
+ store,
51
+ state
52
+ } = fakeStore({
53
+ status: 'succeeded',
54
+ next_action: null,
55
+ last_payment_error: null
56
+ });
57
+ const result = await handleNextAction(store, {
58
+ clientSecret: 'pay_secret'
59
+ });
60
+ expect(result).toEqual({
61
+ status: 'succeeded',
62
+ redirected: false,
63
+ lastPaymentError: null
64
+ });
65
+ // the guard always clears, so a second call is not locked out by the first
66
+ expect(state.nextActionInFlight).toBe(false);
67
+ });
68
+ it('refuses a second call while one is in flight', async () => {
69
+ const {
70
+ store,
71
+ state
72
+ } = fakeStore({
73
+ status: 'succeeded',
74
+ next_action: null,
75
+ last_payment_error: null
76
+ });
77
+ state.nextActionInFlight = true;
78
+ await expect(handleNextAction(store, {
79
+ clientSecret: 'pay_secret'
80
+ })).rejects.toThrow(PaymentsRefusalError);
81
+ await expect(handleNextAction(store, {
82
+ clientSecret: 'pay_secret'
83
+ })).rejects.toThrow(/NEXT_ACTION_IN_FLIGHT/);
84
+ });
85
+ it('clears the guard even when the call throws', async () => {
86
+ const {
87
+ store,
88
+ state
89
+ } = fakeStore({
90
+ status: 'requires_action',
91
+ next_action: {},
92
+ last_payment_error: null
93
+ });
94
+ store.client.payments.retrieveBySecret.mockRejectedValueOnce(new Error('network'));
95
+ await expect(handleNextAction(store, {
96
+ clientSecret: 'pay_secret'
97
+ })).rejects.toThrow('network');
98
+ // a failed step must not lock the handle out of every later attempt
99
+ expect(state.nextActionInFlight).toBe(false);
100
+ });
101
+ });
102
+ //# sourceMappingURL=actions.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["describe","expect","it","vi","mock","WhopAuthSession","present","fn","dismiss","WhopPlatformPay","capability","WALLET_TYPE_FOR_PLATFORM","PaymentsRefusalError","handleNextAction","fakeStore","payment","state","nextActionInFlight","retrieves","store","getSnapshot","patch","next","Object","assign","client","payments","updateBySecret","retrieveBySecret","status","next_action","last_payment_error","result","clientSecret","toEqual","redirected","lastPaymentError","toBe","rejects","toThrow","mockRejectedValueOnce","Error"],"sourceRoot":"../../../src","sources":["controller/actions.test.ts"],"mappings":"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","ignoreList":[]}