@fantastic.dev/better-stripe 0.7.0 → 0.8.1

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 (359) hide show
  1. package/CHANGELOG.md +29 -18
  2. package/README.md +123 -91
  3. package/dist/client/billing/checkout.d.ts +1 -1
  4. package/dist/client/billing/checkout.d.ts.map +1 -1
  5. package/dist/client/billing/checkout.js +7 -2
  6. package/dist/client/billing/checkout.js.map +1 -1
  7. package/dist/client/connect/disputes.d.ts +1 -1
  8. package/dist/client/connect/disputes.d.ts.map +1 -1
  9. package/dist/client/connect/disputes.js +12 -6
  10. package/dist/client/connect/disputes.js.map +1 -1
  11. package/dist/client/connect/paymentMethods.d.ts.map +1 -1
  12. package/dist/client/connect/paymentMethods.js.map +1 -1
  13. package/dist/client/connect/refundActor.d.ts.map +1 -1
  14. package/dist/client/connect/refundActor.js.map +1 -1
  15. package/dist/client/connect/refunds.d.ts.map +1 -1
  16. package/dist/client/connect/refunds.js.map +1 -1
  17. package/dist/client/connect/transfers.d.ts.map +1 -1
  18. package/dist/client/connect/transfers.js +15 -4
  19. package/dist/client/connect/transfers.js.map +1 -1
  20. package/dist/client/core/accountDefaults.d.ts +6 -0
  21. package/dist/client/core/accountDefaults.d.ts.map +1 -0
  22. package/dist/client/core/accountDefaults.js +15 -0
  23. package/dist/client/core/accountDefaults.js.map +1 -0
  24. package/dist/client/core/accounts.d.ts +1 -5
  25. package/dist/client/core/accounts.d.ts.map +1 -1
  26. package/dist/client/core/accounts.js +2 -14
  27. package/dist/client/core/accounts.js.map +1 -1
  28. package/dist/client/core/fees.d.ts.map +1 -1
  29. package/dist/client/core/fees.js +7 -2
  30. package/dist/client/core/fees.js.map +1 -1
  31. package/dist/client/index.d.ts +1 -1
  32. package/dist/client/index.d.ts.map +1 -1
  33. package/dist/client/products/prices.d.ts.map +1 -1
  34. package/dist/client/products/prices.js.map +1 -1
  35. package/dist/client/products/products.d.ts.map +1 -1
  36. package/dist/client/products/products.js +3 -1
  37. package/dist/client/products/products.js.map +1 -1
  38. package/dist/client/utils/owner.d.ts.map +1 -1
  39. package/dist/client/utils/owner.js +3 -1
  40. package/dist/client/utils/owner.js.map +1 -1
  41. package/dist/client/utils/stripeDashboardUrl.d.ts.map +1 -1
  42. package/dist/client/utils/stripeDashboardUrl.js.map +1 -1
  43. package/dist/client/webhooks/helpers.d.ts +10 -0
  44. package/dist/client/webhooks/helpers.d.ts.map +1 -1
  45. package/dist/client/webhooks/helpers.js +18 -0
  46. package/dist/client/webhooks/helpers.js.map +1 -1
  47. package/dist/client/webhooks/processors.d.ts.map +1 -1
  48. package/dist/client/webhooks/processors.js +1 -19
  49. package/dist/client/webhooks/processors.js.map +1 -1
  50. package/dist/component/connect/mutations.d.ts.map +1 -1
  51. package/dist/component/connect/mutations.js +4 -33
  52. package/dist/component/connect/mutations.js.map +1 -1
  53. package/dist/component/connect/schema.d.ts.map +1 -1
  54. package/dist/component/connect/schema.js.map +1 -1
  55. package/dist/component/lib/paymentSeller.d.ts +3 -0
  56. package/dist/component/lib/paymentSeller.d.ts.map +1 -0
  57. package/dist/component/lib/paymentSeller.js +10 -0
  58. package/dist/component/lib/paymentSeller.js.map +1 -0
  59. package/dist/component/lib/reversals.d.ts +10 -0
  60. package/dist/component/lib/reversals.d.ts.map +1 -1
  61. package/dist/component/lib/reversals.js +17 -0
  62. package/dist/component/lib/reversals.js.map +1 -1
  63. package/dist/react/components/ConnectProvider.d.ts +1 -1
  64. package/dist/react/components/ConnectProvider.d.ts.map +1 -1
  65. package/dist/react/components/ConnectProvider.js +18 -4
  66. package/dist/react/components/ConnectProvider.js.map +1 -1
  67. package/dist/react/components/ConnectStatusBadge.d.ts.map +1 -1
  68. package/dist/react/components/ConnectStatusBadge.js.map +1 -1
  69. package/dist/react/components/DisputeDetail.d.ts +4 -1
  70. package/dist/react/components/DisputeDetail.d.ts.map +1 -1
  71. package/dist/react/components/DisputeDetail.js +12 -6
  72. package/dist/react/components/DisputeDetail.js.map +1 -1
  73. package/dist/react/components/DisputesList.d.ts.map +1 -1
  74. package/dist/react/components/DisputesList.js +2 -1
  75. package/dist/react/components/DisputesList.js.map +1 -1
  76. package/dist/react/components/EmbeddedDisputes.d.ts +1 -1
  77. package/dist/react/components/EmbeddedDisputes.d.ts.map +1 -1
  78. package/dist/react/components/EmbeddedDisputes.js +1 -1
  79. package/dist/react/components/EmbeddedDisputes.js.map +1 -1
  80. package/dist/react/components/SplitBreakdown.d.ts.map +1 -1
  81. package/dist/react/components/SplitBreakdown.js +12 -2
  82. package/dist/react/components/SplitBreakdown.js.map +1 -1
  83. package/dist/react/hooks/useCheckoutSession.d.ts.map +1 -1
  84. package/dist/react/hooks/useCheckoutSession.js.map +1 -1
  85. package/dist/react/hooks/useConfirmPayment.d.ts.map +1 -1
  86. package/dist/react/hooks/useConfirmPayment.js.map +1 -1
  87. package/dist/react/index.d.ts +2 -1
  88. package/dist/react/index.d.ts.map +1 -1
  89. package/dist/react/index.js +3 -1
  90. package/dist/react/index.js.map +1 -1
  91. package/dist/react/workflows/Account.d.ts +67 -0
  92. package/dist/react/workflows/Account.d.ts.map +1 -0
  93. package/dist/react/workflows/Account.js +74 -0
  94. package/dist/react/workflows/Account.js.map +1 -0
  95. package/dist/react/workflows/Billing.d.ts +60 -0
  96. package/dist/react/workflows/Billing.d.ts.map +1 -0
  97. package/dist/react/workflows/Billing.js +84 -0
  98. package/dist/react/workflows/Billing.js.map +1 -0
  99. package/dist/react/workflows/BillingPlans.d.ts +45 -0
  100. package/dist/react/workflows/BillingPlans.d.ts.map +1 -0
  101. package/dist/react/workflows/BillingPlans.js +51 -0
  102. package/dist/react/workflows/BillingPlans.js.map +1 -0
  103. package/dist/react/workflows/Checkout.d.ts +46 -0
  104. package/dist/react/workflows/Checkout.d.ts.map +1 -0
  105. package/dist/react/workflows/Checkout.js +61 -0
  106. package/dist/react/workflows/Checkout.js.map +1 -0
  107. package/dist/react/workflows/CheckoutChooser.d.ts +20 -0
  108. package/dist/react/workflows/CheckoutChooser.d.ts.map +1 -0
  109. package/dist/react/workflows/CheckoutChooser.js +24 -0
  110. package/dist/react/workflows/CheckoutChooser.js.map +1 -0
  111. package/dist/react/workflows/CheckoutForms.d.ts +26 -0
  112. package/dist/react/workflows/CheckoutForms.d.ts.map +1 -0
  113. package/dist/react/workflows/CheckoutForms.js +126 -0
  114. package/dist/react/workflows/CheckoutForms.js.map +1 -0
  115. package/dist/react/workflows/ClipboardButton.d.ts +17 -0
  116. package/dist/react/workflows/ClipboardButton.d.ts.map +1 -0
  117. package/dist/react/workflows/ClipboardButton.js +35 -0
  118. package/dist/react/workflows/ClipboardButton.js.map +1 -0
  119. package/dist/react/workflows/Collection.d.ts +30 -0
  120. package/dist/react/workflows/Collection.d.ts.map +1 -0
  121. package/dist/react/workflows/Collection.js +25 -0
  122. package/dist/react/workflows/Collection.js.map +1 -0
  123. package/dist/react/workflows/Collections.d.ts +56 -0
  124. package/dist/react/workflows/Collections.d.ts.map +1 -0
  125. package/dist/react/workflows/Collections.js +111 -0
  126. package/dist/react/workflows/Collections.js.map +1 -0
  127. package/dist/react/workflows/Connect.d.ts +19 -0
  128. package/dist/react/workflows/Connect.d.ts.map +1 -0
  129. package/dist/react/workflows/Connect.js +43 -0
  130. package/dist/react/workflows/Connect.js.map +1 -0
  131. package/dist/react/workflows/Costs.d.ts +48 -0
  132. package/dist/react/workflows/Costs.d.ts.map +1 -0
  133. package/dist/react/workflows/Costs.js +66 -0
  134. package/dist/react/workflows/Costs.js.map +1 -0
  135. package/dist/react/workflows/Disputes.d.ts +36 -0
  136. package/dist/react/workflows/Disputes.d.ts.map +1 -0
  137. package/dist/react/workflows/Disputes.js +74 -0
  138. package/dist/react/workflows/Disputes.js.map +1 -0
  139. package/dist/react/workflows/Earnings.d.ts +42 -0
  140. package/dist/react/workflows/Earnings.d.ts.map +1 -0
  141. package/dist/react/workflows/Earnings.js +38 -0
  142. package/dist/react/workflows/Earnings.js.map +1 -0
  143. package/dist/react/workflows/Financials.d.ts +43 -0
  144. package/dist/react/workflows/Financials.d.ts.map +1 -0
  145. package/dist/react/workflows/Financials.js +57 -0
  146. package/dist/react/workflows/Financials.js.map +1 -0
  147. package/dist/react/workflows/IntegrationSwitch.d.ts +23 -0
  148. package/dist/react/workflows/IntegrationSwitch.d.ts.map +1 -0
  149. package/dist/react/workflows/IntegrationSwitch.js +31 -0
  150. package/dist/react/workflows/IntegrationSwitch.js.map +1 -0
  151. package/dist/react/workflows/Onboarding.d.ts +56 -0
  152. package/dist/react/workflows/Onboarding.d.ts.map +1 -0
  153. package/dist/react/workflows/Onboarding.js +86 -0
  154. package/dist/react/workflows/Onboarding.js.map +1 -0
  155. package/dist/react/workflows/Overview.d.ts +51 -0
  156. package/dist/react/workflows/Overview.d.ts.map +1 -0
  157. package/dist/react/workflows/Overview.js +63 -0
  158. package/dist/react/workflows/Overview.js.map +1 -0
  159. package/dist/react/workflows/PaymentMethods.d.ts +35 -0
  160. package/dist/react/workflows/PaymentMethods.d.ts.map +1 -0
  161. package/dist/react/workflows/PaymentMethods.js +63 -0
  162. package/dist/react/workflows/PaymentMethods.js.map +1 -0
  163. package/dist/react/workflows/PaymentReceipt.d.ts +20 -0
  164. package/dist/react/workflows/PaymentReceipt.d.ts.map +1 -0
  165. package/dist/react/workflows/PaymentReceipt.js +24 -0
  166. package/dist/react/workflows/PaymentReceipt.js.map +1 -0
  167. package/dist/react/workflows/Payouts.d.ts +48 -0
  168. package/dist/react/workflows/Payouts.d.ts.map +1 -0
  169. package/dist/react/workflows/Payouts.js +88 -0
  170. package/dist/react/workflows/Payouts.js.map +1 -0
  171. package/dist/react/workflows/Products.d.ts +92 -0
  172. package/dist/react/workflows/Products.d.ts.map +1 -0
  173. package/dist/react/workflows/Products.js +179 -0
  174. package/dist/react/workflows/Products.js.map +1 -0
  175. package/dist/react/workflows/ReferralLinks.d.ts +26 -0
  176. package/dist/react/workflows/ReferralLinks.d.ts.map +1 -0
  177. package/dist/react/workflows/ReferralLinks.js +30 -0
  178. package/dist/react/workflows/ReferralLinks.js.map +1 -0
  179. package/dist/react/workflows/Refunds.d.ts +72 -0
  180. package/dist/react/workflows/Refunds.d.ts.map +1 -0
  181. package/dist/react/workflows/Refunds.js +95 -0
  182. package/dist/react/workflows/Refunds.js.map +1 -0
  183. package/dist/react/workflows/Setup.d.ts +50 -0
  184. package/dist/react/workflows/Setup.d.ts.map +1 -0
  185. package/dist/react/workflows/Setup.js +59 -0
  186. package/dist/react/workflows/Setup.js.map +1 -0
  187. package/dist/react/workflows/Storefront.d.ts +53 -0
  188. package/dist/react/workflows/Storefront.d.ts.map +1 -0
  189. package/dist/react/workflows/Storefront.js +44 -0
  190. package/dist/react/workflows/Storefront.js.map +1 -0
  191. package/dist/react/workflows/SubscriptionOverview.d.ts +13 -0
  192. package/dist/react/workflows/SubscriptionOverview.d.ts.map +1 -0
  193. package/dist/react/workflows/SubscriptionOverview.js +26 -0
  194. package/dist/react/workflows/SubscriptionOverview.js.map +1 -0
  195. package/dist/react/workflows/Subscriptions.d.ts +92 -0
  196. package/dist/react/workflows/Subscriptions.d.ts.map +1 -0
  197. package/dist/react/workflows/Subscriptions.js +149 -0
  198. package/dist/react/workflows/Subscriptions.js.map +1 -0
  199. package/dist/react/workflows/Tasks.d.ts +40 -0
  200. package/dist/react/workflows/Tasks.d.ts.map +1 -0
  201. package/dist/react/workflows/Tasks.js +113 -0
  202. package/dist/react/workflows/Tasks.js.map +1 -0
  203. package/dist/react/workflows/checkout-options.d.ts +37 -0
  204. package/dist/react/workflows/checkout-options.d.ts.map +1 -0
  205. package/dist/react/workflows/checkout-options.js +43 -0
  206. package/dist/react/workflows/checkout-options.js.map +1 -0
  207. package/dist/react/workflows/current-subscription.d.ts +11 -0
  208. package/dist/react/workflows/current-subscription.d.ts.map +1 -0
  209. package/dist/react/workflows/current-subscription.js +14 -0
  210. package/dist/react/workflows/current-subscription.js.map +1 -0
  211. package/dist/react/workflows/filters.d.ts +17 -0
  212. package/dist/react/workflows/filters.d.ts.map +1 -0
  213. package/dist/react/workflows/filters.js +23 -0
  214. package/dist/react/workflows/filters.js.map +1 -0
  215. package/dist/react/workflows/index.d.ts +70 -0
  216. package/dist/react/workflows/index.d.ts.map +1 -0
  217. package/dist/react/workflows/index.js +38 -0
  218. package/dist/react/workflows/index.js.map +1 -0
  219. package/dist/react/workflows/useWorkflowAction.d.ts +11 -0
  220. package/dist/react/workflows/useWorkflowAction.d.ts.map +1 -0
  221. package/dist/react/workflows/useWorkflowAction.js +68 -0
  222. package/dist/react/workflows/useWorkflowAction.js.map +1 -0
  223. package/dist/react/workflows/useWorkflowResource.d.ts +9 -0
  224. package/dist/react/workflows/useWorkflowResource.d.ts.map +1 -0
  225. package/dist/react/workflows/useWorkflowResource.js +67 -0
  226. package/dist/react/workflows/useWorkflowResource.js.map +1 -0
  227. package/docs/react-workflows-audit.md +88 -0
  228. package/docs/react-workflows.md +234 -0
  229. package/package.json +19 -3
  230. package/src/client/billing/checkout-ui-modes.test.ts +49 -0
  231. package/src/client/billing/checkout.ts +8 -3
  232. package/src/client/billing/invoices.test.ts +12 -6
  233. package/src/client/connect/disputes.test.ts +15 -0
  234. package/src/client/connect/disputes.ts +13 -7
  235. package/src/client/connect/paymentMethods.test.ts +3 -1
  236. package/src/client/connect/paymentMethods.ts +4 -1
  237. package/src/client/connect/refundActor.ts +1 -2
  238. package/src/client/connect/refunds.test.ts +35 -10
  239. package/src/client/connect/refunds.ts +4 -1
  240. package/src/client/connect/transfers.test.ts +66 -12
  241. package/src/client/connect/transfers.ts +32 -8
  242. package/src/client/core/accountDefaults.ts +15 -0
  243. package/src/client/core/accounts.ts +14 -17
  244. package/src/client/core/config.test.ts +2 -1
  245. package/src/client/core/descriptors.test.ts +6 -4
  246. package/src/client/core/fees.test.ts +20 -28
  247. package/src/client/core/fees.ts +9 -2
  248. package/src/client/index.test.ts +22 -22
  249. package/src/client/index.ts +1 -1
  250. package/src/client/products/prices.test.ts +8 -2
  251. package/src/client/products/prices.ts +4 -1
  252. package/src/client/products/products.test.ts +61 -20
  253. package/src/client/products/products.ts +3 -1
  254. package/src/client/utils/data.test.ts +3 -1
  255. package/src/client/utils/owner.test.ts +4 -1
  256. package/src/client/utils/owner.ts +5 -1
  257. package/src/client/utils/stripeDashboardUrl.ts +1 -4
  258. package/src/client/webhooks/handler.test.ts +16 -19
  259. package/src/client/webhooks/helpers.test.ts +26 -13
  260. package/src/client/webhooks/helpers.ts +23 -0
  261. package/src/client/webhooks/hooks.test.ts +1 -2
  262. package/src/client/webhooks/processors.test.ts +18 -34
  263. package/src/client/webhooks/processors.ts +1 -23
  264. package/src/client/webhooks.test.ts +1 -2
  265. package/src/component/_generated/api.ts +2 -0
  266. package/src/component/connect/mutations.ts +5 -46
  267. package/src/component/connect/schema.ts +4 -3
  268. package/src/component/connect.test.ts +1 -5
  269. package/src/component/lib/paymentSeller.ts +15 -0
  270. package/src/component/lib/reversals.ts +30 -2
  271. package/src/component/subscription-scoping.test.ts +5 -1
  272. package/src/component/triggers.test.ts +7 -4
  273. package/src/react/components/BuyerBillingView.render.test.tsx +7 -2
  274. package/src/react/components/ConnectProvider.live.test.tsx +61 -0
  275. package/src/react/components/ConnectProvider.tsx +18 -4
  276. package/src/react/components/ConnectStatusBadge.tsx +1 -4
  277. package/src/react/components/DisputeDetail.render.test.tsx +5 -1
  278. package/src/react/components/DisputeDetail.tsx +14 -5
  279. package/src/react/components/DisputesList.render.test.tsx +21 -0
  280. package/src/react/components/DisputesList.tsx +2 -1
  281. package/src/react/components/EarningsSummary.render.test.tsx +2 -6
  282. package/src/react/components/EmbeddedDisputes.render.test.tsx +7 -5
  283. package/src/react/components/EmbeddedDisputes.tsx +4 -1
  284. package/src/react/components/EvidenceForm.render.test.tsx +3 -10
  285. package/src/react/components/SplitBreakdown.render.test.tsx +28 -5
  286. package/src/react/components/SplitBreakdown.tsx +12 -2
  287. package/src/react/hooks/useCheckoutSession.ts +1 -2
  288. package/src/react/hooks/useConfirmPayment.ts +1 -2
  289. package/src/react/hooks/useEarnings.test.ts +43 -8
  290. package/src/react/hooks/useStripeMode.test.ts +5 -8
  291. package/src/react/index.ts +7 -1
  292. package/src/react/workflows/Account.test.tsx +31 -0
  293. package/src/react/workflows/Account.tsx +183 -0
  294. package/src/react/workflows/Billing.test.tsx +45 -0
  295. package/src/react/workflows/Billing.tsx +213 -0
  296. package/src/react/workflows/BillingPlans.test.tsx +31 -0
  297. package/src/react/workflows/BillingPlans.tsx +130 -0
  298. package/src/react/workflows/Checkout.test.tsx +118 -0
  299. package/src/react/workflows/Checkout.tsx +135 -0
  300. package/src/react/workflows/CheckoutChooser.test.tsx +44 -0
  301. package/src/react/workflows/CheckoutChooser.tsx +77 -0
  302. package/src/react/workflows/CheckoutForm.test.tsx +66 -0
  303. package/src/react/workflows/CheckoutForms.test.tsx +123 -0
  304. package/src/react/workflows/CheckoutForms.tsx +247 -0
  305. package/src/react/workflows/ClipboardButton.test.tsx +34 -0
  306. package/src/react/workflows/ClipboardButton.tsx +67 -0
  307. package/src/react/workflows/Collection.tsx +76 -0
  308. package/src/react/workflows/Collections.test.tsx +86 -0
  309. package/src/react/workflows/Collections.tsx +213 -0
  310. package/src/react/workflows/Connect.test.tsx +50 -0
  311. package/src/react/workflows/Connect.tsx +107 -0
  312. package/src/react/workflows/Costs.test.tsx +41 -0
  313. package/src/react/workflows/Costs.tsx +133 -0
  314. package/src/react/workflows/Disputes.test.tsx +64 -0
  315. package/src/react/workflows/Disputes.tsx +173 -0
  316. package/src/react/workflows/Earnings.test.ts +19 -0
  317. package/src/react/workflows/Earnings.tsx +84 -0
  318. package/src/react/workflows/Financials.test.tsx +35 -0
  319. package/src/react/workflows/Financials.tsx +117 -0
  320. package/src/react/workflows/IntegrationSwitch.test.tsx +36 -0
  321. package/src/react/workflows/IntegrationSwitch.tsx +63 -0
  322. package/src/react/workflows/Onboarding.test.tsx +75 -0
  323. package/src/react/workflows/Onboarding.tsx +171 -0
  324. package/src/react/workflows/Overview.test.tsx +57 -0
  325. package/src/react/workflows/Overview.tsx +123 -0
  326. package/src/react/workflows/PaymentMethods.test.tsx +60 -0
  327. package/src/react/workflows/PaymentMethods.tsx +117 -0
  328. package/src/react/workflows/PaymentReceipt.test.tsx +24 -0
  329. package/src/react/workflows/PaymentReceipt.tsx +46 -0
  330. package/src/react/workflows/Payouts.test.tsx +112 -0
  331. package/src/react/workflows/Payouts.tsx +215 -0
  332. package/src/react/workflows/Products.test.tsx +90 -0
  333. package/src/react/workflows/Products.tsx +377 -0
  334. package/src/react/workflows/ReferralLinks.test.tsx +39 -0
  335. package/src/react/workflows/ReferralLinks.tsx +75 -0
  336. package/src/react/workflows/Refunds.test.tsx +75 -0
  337. package/src/react/workflows/Refunds.tsx +223 -0
  338. package/src/react/workflows/Setup.test.tsx +25 -0
  339. package/src/react/workflows/Setup.tsx +166 -0
  340. package/src/react/workflows/Storefront.test.tsx +82 -0
  341. package/src/react/workflows/Storefront.tsx +138 -0
  342. package/src/react/workflows/SubscriptionOverview.test.tsx +27 -0
  343. package/src/react/workflows/SubscriptionOverview.tsx +48 -0
  344. package/src/react/workflows/Subscriptions.test.tsx +61 -0
  345. package/src/react/workflows/Subscriptions.tsx +282 -0
  346. package/src/react/workflows/Tasks.test.tsx +23 -0
  347. package/src/react/workflows/Tasks.tsx +199 -0
  348. package/src/react/workflows/checkout-options.ts +42 -0
  349. package/src/react/workflows/current-subscription.test.ts +29 -0
  350. package/src/react/workflows/current-subscription.ts +25 -0
  351. package/src/react/workflows/filters.test.ts +12 -0
  352. package/src/react/workflows/filters.ts +22 -0
  353. package/src/react/workflows/index.ts +238 -0
  354. package/src/react/workflows/native-interactions.test.tsx +73 -0
  355. package/src/react/workflows/public-workflows.test.tsx +216 -0
  356. package/src/react/workflows/useWorkflowAction.test.tsx +54 -0
  357. package/src/react/workflows/useWorkflowAction.ts +75 -0
  358. package/src/react/workflows/useWorkflowResource.test.tsx +41 -0
  359. package/src/react/workflows/useWorkflowResource.ts +78 -0
@@ -0,0 +1,88 @@
1
+ # Example UI audit
2
+
3
+ Every financial/account page has a public React component or workflow hook in
4
+ `@fantastic.dev/better-stripe/react`. Native unstyled components implement the
5
+ shared workflows. The example binds authenticated Convex queries/actions and
6
+ uses render props or companion hooks to apply shadcn styling.
7
+
8
+ | Example page or adapter | Package UI and workflow ownership |
9
+ | ----------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ |
10
+ | Home and stores | `Storefront`, including store filtering, active catalog prices, purchase actions, and referral attribution |
11
+ | Checkout chooser | `CheckoutChooser`, `CHECKOUT_OPTIONS`, recurring-product compatibility and selection |
12
+ | Checkout session / PaymentIntent adapters | `Checkout`, `CheckoutElementsForm`, `PaymentIntentForm`, `CheckoutForm`, `EmbeddedCheckout`, including loading, retry, validation and confirmation |
13
+ | Checkout status | `CheckoutStatus`, `PaymentReceipt`, server/webhook confirmation |
14
+ | Customer overview | `SubscriptionOverview` |
15
+ | Customer subscription billing | `useSubscriptionManager`, `SubscriptionManager`, `BuyerBillingView`, `SubscriptionCard`, `Invoices`, `BillingPortalLink` |
16
+ | Customer invoices | `Invoices` |
17
+ | Customer payment methods | `usePaymentMethodsManager`, `PaymentMethods`, `PaymentMethodsList`, `AddCardForm`, Stripe providers |
18
+ | Seller overview | `PayoutOverview`, `AccountCreateCard`, `ConnectStatusBadge` |
19
+ | Seller and affiliate payouts | `Payouts`, `PayoutHistory`, live balances, upcoming date, history and pagination |
20
+ | Seller earnings | `EarningsSummary`, `PayoutSchedule`, `PayoutHistory`, `earningsFromBalance`, `useWorkflowResource` |
21
+ | Seller sales | `Sales` |
22
+ | Seller subscriptions | `Subscriptions`, `SubscriptionCard` |
23
+ | Seller and admin products | `useProductManager`, `Products`, `PriceCard`, product/price creation, editing and archiving |
24
+ | Seller account details | `useAccountManager`, `Account`, `AccountLoginCard`, `ConnectRequirements` |
25
+ | Seller onboarding / account setup | `useOnboarding`, `Onboarding`, `AccountCloseCard`, `DEFAULT_CONNECT_COUNTRIES` |
26
+ | Seller marketplace account | Account/onboarding hooks, `AccountConfigurations`, `ConnectStatusBadge`, `CheckoutStatus`, shared action lifecycle |
27
+ | Seller billing | `usePlanBilling`, `BillingPlans`, `EmbeddedCheckout`, `useInvoiceEstimate`, `InvoiceEstimate`, `useBalanceFunding`, `BalancePaymentSource` |
28
+ | Seller refunds | `useRefunds`, `Refunds`, `RefundHistory`, `PaymentDetails`, `CostRecovery` |
29
+ | Seller disputes | `useDisputeResponse`, `Disputes`, `DisputesList`, `DisputeDetail`, `EvidenceForm`, `ChargebackLedger`, `CostRecovery` |
30
+ | Affiliate earnings | `Earnings`, `EarningsSummary` |
31
+ | Affiliate referred sales | `ReferredSales`, store attribution and commission |
32
+ | Affiliate links | `useReferralLinks`, `ReferralLinks`, `ClipboardButton` |
33
+ | Admin overview | `Overview` |
34
+ | Admin subscriptions | `Subscriptions`, `useSubscriptionFilter` |
35
+ | Admin webhooks | `WebhookEvents`, `useWebhookFilters` |
36
+ | Admin setup | `useWebhookSetup`, `WebhookSetup`, `EnvironmentStatus`, `FixtureProgress`, `useTaskRunner`, `StripeSetup`, `ClipboardButton`, shared actions/resources |
37
+ | Admin sandbox testing | `useTaskRunner`, `SandboxTesting`, `WorkflowTasks` |
38
+ | Legacy affiliate split demo | `Checkout`, `SplitBreakdown`, `EarningsSummary`, bound package hook factories |
39
+ | Legacy destination-charge module | `Checkout`, `ChargeSummary`; the legacy public route currently resolves to the split demo |
40
+ | Integration presentation switch | `IntegrationSwitch`; only the active view mounts |
41
+ | Connect alternatives | `Connect` with account management, onboarding, payments/refunds, disputes, balances, payouts and notifications |
42
+ | Styled shared tables | `Collection` and domain collections; `WorkflowTable` only maps their state/columns to shadcn |
43
+
44
+ The example owns app branding, navigation, theme controls, the persona/store
45
+ switcher, route guards, URL state, and styling. It also owns its users and
46
+ server bindings, fee plans, referral-share policy, recovery billing rules,
47
+ sandbox scenario definitions, and authorization. These are application choices,
48
+ not prerequisites imposed by the public React package.
49
+
50
+ Some examples use companion hooks with styled markup instead of mounting the
51
+ native component. That markup changes presentation; the package owns the
52
+ workflow state, validation, duplicate-action handling, and async errors. Reusable
53
+ native components exist for consumers who do not want to write those renderers.
54
+ Connect and hosted Stripe UI remain available only where Stripe supports them.
55
+
56
+ ## Verification
57
+
58
+ - Public-entry tests render native components without example providers, routing,
59
+ CSS classes, or inline styling and without calling server actions during render.
60
+ - Interaction tests exercise native product-price creation, partial refunds,
61
+ balance consent, checkout selection, and other workflow controllers.
62
+ - Account changes and duplicate actions have regression tests.
63
+ - Browser smoke coverage visits all five personas' pages and the integration views.
64
+ - Checkout tests complete referred guest purchases through all five integrations
65
+ in a Stripe sandbox and verify webhook receipts and settlement.
66
+ - `pnpm run check:all` enforces all repository gates, including Shadscan at 100.
67
+
68
+ ## Follow-up audit
69
+
70
+ The final sandbox QA and follow-up audit checked every example route and its
71
+ adapters against the public React exports. Checkout delegates through the
72
+ session and PaymentIntent adapters. The remaining local state controls the
73
+ app's command menu, mobile sidebar, URL parameters, or selected demo price.
74
+ Financial actions use package workflow controllers or components.
75
+
76
+ The follow-up removed payout-status filtering from the example. Both native
77
+ `Payouts` and its render-prop example now consume the package's
78
+ `upcomingPayouts`, `previousPayouts`, and `nextPayout`. Regression tests cover
79
+ mixed payout statuses and arrival ordering. Dispute lists and detail views hide
80
+ stale evidence deadlines after a dispute leaves a response-required status.
81
+
82
+ Live browser checks cover reset/reseed, all persona routes, integration tabs,
83
+ five checkout integrations, saved-card add/remove and persistence, product
84
+ editing, subscription pause/resume, invoice estimates, balance-payment consent,
85
+ affiliate link copying, dispute evidence, and partial/remaining-balance refunds.
86
+ The tests use Stripe sandbox objects and await action results or webhook state.
87
+ Native public-entry tests also render the workflows without example providers,
88
+ CSS classes, inline styles, or example URLs.
@@ -0,0 +1,234 @@
1
+ # React workflows
2
+
3
+ Import the example's reusable UI and workflow hooks from
4
+ `@fantastic.dev/better-stripe/react`. You do not need the example's route tree,
5
+ role provider, Tailwind, or shadcn components.
6
+
7
+ Components render semantic HTML without package CSS. Use their render props or
8
+ companion hooks to supply your own design system. Stripe iframe contents use
9
+ Stripe's `appearance` options and retain Stripe's own styling.
10
+
11
+ ## Bind your backend
12
+
13
+ Pass authenticated server callbacks and query results to the components. This
14
+ keeps your user IDs, authorization, database schema, and business rules in your
15
+ application. The example's pages demonstrate Convex adapters for these callbacks.
16
+ A callback is an API contract, not an authorization boundary. The server must
17
+ check account ownership, price IDs, amounts, referral attribution, and permissions.
18
+
19
+ `scopeKey` identifies the authenticated account or customer. Change it when that
20
+ identity changes so pending responses cannot populate another account's UI.
21
+ For checkout, change `orderKey` when the customer, price, or attribution changes.
22
+ Do not put secret keys in these props. Browser code needs only a publishable key
23
+ and short-lived client secrets returned by your server.
24
+
25
+ ## Choose a checkout
26
+
27
+ `Checkout` supports all five checkout integrations. It creates the session or
28
+ PaymentIntent, handles loading and retry, mounts the required Stripe provider,
29
+ and reports confirmation errors. Hosted Checkout waits for an explicit click.
30
+ `CheckoutChooser` renders the five choices and their pros and cons. It supports
31
+ controlled selection, render props, and a recurring-product compatibility notice.
32
+ `CHECKOUT_OPTIONS` also exports the descriptions.
33
+
34
+ ```tsx
35
+ import { Checkout } from "@fantastic.dev/better-stripe/react";
36
+
37
+ // createSession is your authenticated server binding. It must validate priceId.
38
+ function Purchase({ publishableKey, priceId, createSession }) {
39
+ return (
40
+ <Checkout
41
+ mode="custom"
42
+ publishableKey={publishableKey}
43
+ orderKey={priceId}
44
+ returnUrl={`${window.location.origin}/receipt?session_id={CHECKOUT_SESSION_ID}`}
45
+ createSession={({ mode, requestId }) =>
46
+ createSession({ priceId, uiMode: mode, requestId })
47
+ }
48
+ />
49
+ );
50
+ }
51
+ ```
52
+
53
+ The callback returns `{ stripeSessionId, clientSecret?, url? }`. It must return
54
+ `url` for `redirect` and `clientSecret` for the other session modes. Use the
55
+ request ID for server idempotency. A user-triggered retry creates a new request
56
+ ID; also enforce application-level duplicate-order protection on the server.
57
+
58
+ | Mode | Stripe integration | Tradeoff |
59
+ | ---------------- | ------------------------------------- | ---------------------------------------------------------------------- |
60
+ | `redirect` | Hosted Checkout Session | Least UI work, leaves your app |
61
+ | `embedded` | Embedded Checkout Session | Complete Stripe checkout in your page, less layout control |
62
+ | `custom` | Checkout Session with Payment Element | Custom form layout with Checkout's session model |
63
+ | `payment-intent` | PaymentIntent with Payment Element | Payment control, application owns order and subscription orchestration |
64
+ | `form` | Preview Embedded Checkout Form | Compact Stripe form, requires the supported Stripe preview |
65
+
66
+ For `payment-intent`, provide `createPaymentIntent({ requestId })` instead of
67
+ `createSession`. Return `{ paymentIntentId, clientSecret }`. Payment Intents do
68
+ not create subscriptions. Stripe.js supplies the browser SDK and publishable-key
69
+ handling for these flows; it is not a separate server payment model.
70
+
71
+ Use `renderForm` on the custom and PaymentIntent modes to render your own email
72
+ input, `paymentElement`, error, and submit button. The preview `form` mode renders
73
+ Stripe's form and does not use that renderer. `children` replaces the outer
74
+ checkout frame and receives `content`, `isLoading`, `error`, and `retry`.
75
+ The lower-level `CheckoutElementsForm`, `PaymentIntentForm`, and `CheckoutForm`
76
+ are also exported for an existing client secret.
77
+
78
+ Only a server-confirmed payment or checkout session should grant access to the
79
+ product. Use `PaymentReceipt` or `CheckoutStatus` with webhook-backed query data;
80
+ a browser return URL alone does not prove payment.
81
+
82
+ ## Headless or Stripe embedded
83
+
84
+ `Account`, `Onboarding`, `Disputes`, `Refunds`, `Earnings`, and `Payouts` accept
85
+ `presentation="embedded"` with Connect session props. Their default headless
86
+ presentation accepts domain-specific data and callbacks. `Connect` also exposes
87
+ account, onboarding, payments, refunds, disputes, balances, payouts, and
88
+ notifications widgets directly.
89
+
90
+ ```tsx
91
+ import { IntegrationSwitch, Payouts } from "@fantastic.dev/better-stripe/react";
92
+
93
+ function AccountPayouts({
94
+ accountId,
95
+ publishableKey,
96
+ loadPayouts,
97
+ createSession,
98
+ }) {
99
+ return (
100
+ <IntegrationSwitch
101
+ views={{
102
+ headless: <Payouts scopeKey={accountId} load={loadPayouts} />,
103
+ embedded: (
104
+ <Payouts
105
+ presentation="embedded"
106
+ scopeKey={accountId}
107
+ publishableKey={publishableKey}
108
+ fetchClientSecret={async () => (await createSession()).clientSecret}
109
+ />
110
+ ),
111
+ }}
112
+ />
113
+ );
114
+ }
115
+ ```
116
+
117
+ The server creates an Account Session for the authenticated connected account
118
+ and enables the requested component and features. Session refresh uses the latest callback. Appearance and locale updates apply
119
+ to the active Connect instance without remounting it. Changing the publishable
120
+ key creates a new instance. `IntegrationSwitch` mounts only the active view and has
121
+ no router dependency. It also supports controlled `value`/`onValueChange` and
122
+ `components` and `hosted` views when your workflow has those alternatives.
123
+
124
+ Connect displays only the payment data supported for that connected account.
125
+ The example's platform-owned separate-charges-and-transfers ledger remains in
126
+ its headless sales/refund/dispute views. A Connect embed cannot turn that ledger
127
+ into connected-account-owned charges. Refunds use the Connect Payments widget;
128
+ there is no separate Connect refund catalog widget. Product management,
129
+ customer subscriptions, and platform billing do not have equivalent Connect
130
+ widgets. Use package UI or the hosted Billing Portal for those workflows.
131
+
132
+ ## Component and hook reference
133
+
134
+ | Workflow | Unstyled components | Companion hooks/helpers |
135
+ | --------------------- | -------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------- |
136
+ | Store browsing | `Storefront`, `PriceCard` | Store/product/price models and purchase callbacks |
137
+ | Checkout | `CheckoutChooser`, `Checkout`, `CheckoutElementsForm`, `PaymentIntentForm`, `CheckoutForm`, `EmbeddedCheckout` | `CHECKOUT_OPTIONS` |
138
+ | Receipts | `PaymentReceipt`, `CheckoutStatus` | Server-backed payment/session data |
139
+ | Earnings | `Earnings`, `EarningsSummary` | `earningsFromBalance` |
140
+ | Payouts | `Payouts`, `PayoutSchedule`, `PayoutHistory`, `PayoutOverview` | `getPayoutTotals` |
141
+ | Sales | `Sales`, `ReferredSales` | Server-authoritative economic rows |
142
+ | Refunds | `Refunds`, `RefundHistory` | `useRefunds`, `parseAmountCents` |
143
+ | Disputes | `Disputes`, `DisputesList`, `DisputeDetail`, `EvidenceForm`, `ChargebackLedger` | `useDisputeResponse` |
144
+ | Onboarding | `Onboarding` | `useOnboarding` |
145
+ | Accounts | `Account`, `AccountConfigurations` | `useAccountManager` |
146
+ | Product management | `Products` | `useProductManager` |
147
+ | Subscriptions | `Subscriptions`, `SubscriptionManager`, `SubscriptionOverview`, `SubscriptionCard` | `useSubscriptionManager`, `useSubscriptionFilter`, `currentSubscriptionFrom` |
148
+ | Billing | `BillingPlans`, `BillingPortal`, `InvoiceEstimate`, `Invoices`, `BalancePaymentSource` | `usePlanBilling`, `useInvoiceEstimate`, `useBalanceFunding` |
149
+ | Payment methods | `PaymentMethods`, `PaymentMethodsList`, `AddCardForm` | `usePaymentMethodsManager`, `toPaymentMethodItem` |
150
+ | Seller cost recovery | `CostRecovery` | Server-calculated outstanding/collected/invoiced amounts |
151
+ | Referral sharing | `ReferralLinks`, `ClipboardButton` | `useReferralLinks` |
152
+ | Admin | `Overview`, `WebhookEvents` | `useWebhookFilters`, `webhookQueryArgs` |
153
+ | Sandbox setup/testing | `StripeSetup`, `SandboxTesting`, `WorkflowTasks`, `WebhookSetup`, `EnvironmentStatus`, `FixtureProgress` | `useTaskRunner`, `useWebhookSetup` |
154
+ | Shared state/tables | `IntegrationSwitch`, `Collection` | `useWorkflowAction`, `useWorkflowResource` |
155
+
156
+ The example still owns its navigation, persona switcher, application branding,
157
+ server authorization, sandbox fixture definitions, and marketplace fee policy.
158
+ Its styled forms and tables consume package hooks/render props. The package's
159
+ default components implement those workflows without the example's providers.
160
+ The package does not seed or reset a Stripe account just because a component
161
+ mounts. Setup/testing tasks call the operations you explicitly bind.
162
+
163
+ ## Data contracts and styling
164
+
165
+ `Payouts.load(cursor?)` returns a `PayoutSnapshot` with `balances`, `payouts`,
166
+ `upcoming`, and `nextCursor`. Each balance has `currency`, `available`, and
167
+ `pending`. Payout rows include `id`, `amount`, `currency`, `status`, `arrivalDate`,
168
+ and `created`. The component shows available and pending balances, the next
169
+ known payout and arrival date, upcoming payouts, and paginated previous payouts.
170
+ Render props expose `upcomingPayouts` sorted by arrival date,
171
+ `previousPayouts`, and `nextPayout`. Use these package-owned classifications
172
+ in custom UI; completed or failed payouts are excluded from upcoming payouts.
173
+ If Stripe has not provided an upcoming payout, the UI says so rather than
174
+ inventing a date.
175
+
176
+ Payout, invoice-estimate, cost, and webhook timestamps use Unix milliseconds.
177
+ Subscription period/trial fields use ISO date strings, matching the existing
178
+ subscription API. Convert raw Stripe Unix seconds in your adapter. Money values use integer minor units. The current decimal refund
179
+ input and price-formatting helpers use two decimal places, as in the USD
180
+ example. Supply custom rendering/input conversion for zero-decimal and
181
+ three-decimal currencies. Never combine balances across currencies.
182
+
183
+ Sale fees, affiliate shares, recovery costs, invoice estimates, and settlement
184
+ statuses come from server data. The UI does not recalculate the example's fee
185
+ policy or charge outstanding costs by itself. Balance funding requires explicit
186
+ consent and a server integration with Stripe's supported preview. Card fallback,
187
+ renewal recovery, and debt collection remain server business rules.
188
+
189
+ Use exported `*Props`, row models, and render-state types for typed adapters.
190
+ Tables accept optional columns and a `children(state)` renderer. Action hooks
191
+ expose pending, error, and results so your buttons and alerts share the same
192
+ validation and duplicate-submit handling as the native components.
193
+
194
+ ```tsx
195
+ import { Invoices } from "@fantastic.dev/better-stripe/react";
196
+
197
+ function InvoiceList({ invoices }) {
198
+ return (
199
+ <Invoices rows={invoices}>
200
+ {({ rows, isLoading, isEmpty }) =>
201
+ isLoading ? (
202
+ <p>Loading invoices…</p>
203
+ ) : isEmpty ? (
204
+ <p>No invoices yet.</p>
205
+ ) : (
206
+ <ul>
207
+ {rows.map((row) => (
208
+ <li key={row.stripeInvoiceId}>{row.stripeInvoiceId}</li>
209
+ ))}
210
+ </ul>
211
+ )
212
+ }
213
+ </Invoices>
214
+ );
215
+ }
216
+ ```
217
+
218
+ Default markup has `data-better-stripe` attributes for scoped CSS. Use render
219
+ props to replace markup with your design system, including labels and locale
220
+ formatting. A render function replaces the supplied markup; render its `content`
221
+ or `paymentElement` where those are part of the state's contract.
222
+
223
+ ## Example coverage
224
+
225
+ See [the page audit](react-workflows-audit.md) for the mapping from every example
226
+ page to package components and hooks. `ChargeSummary` displays server-calculated
227
+ charge/fee/payout figures. `PaymentDetails` displays recorded charge and refund
228
+ state. `PayoutOverview` shows payout activity totals, which are separate from the
229
+ available and pending Stripe balances shown by `Payouts`.
230
+
231
+ `DEFAULT_CONNECT_COUNTRIES` provides the example's eight country choices and is
232
+ shared by its account pages and native `Onboarding`. Supply `countries` to limit
233
+ or expand the UI for your platform. This default is not a complete list of
234
+ Stripe-supported countries; your server must validate account eligibility.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fantastic.dev/better-stripe",
3
- "version": "0.7.0",
3
+ "version": "0.8.1",
4
4
  "description": "A Convex component for Stripe V2 Accounts API integration.",
5
5
  "keywords": [
6
6
  "stripe",
@@ -57,6 +57,8 @@
57
57
  "files": [
58
58
  "dist",
59
59
  "src",
60
+ "docs/react-workflows.md",
61
+ "docs/react-workflows-audit.md",
60
62
  "CHANGELOG.md",
61
63
  "MIGRATION.md"
62
64
  ],
@@ -83,7 +85,18 @@
83
85
  "prepublishOnly": "npm run clean && npm run build && npm run typecheck",
84
86
  "test": "vitest run",
85
87
  "test:watch": "vitest",
86
- "test:coverage": "vitest run --coverage"
88
+ "test:coverage": "vitest run --coverage",
89
+ "check:design-system": "eslint --config eslint.design-system.config.mjs . --max-warnings 0",
90
+ "check:shadscan": "shadscan \"./example\" --json --fail-under 100 --no-roast --no-interactive",
91
+ "check:all": "repo-gates check-all",
92
+ "check:size": "repo-gates check-size",
93
+ "check:debt": "repo-gates check-debt",
94
+ "check:circular": "repo-gates check-circular",
95
+ "check:secrets": "repo-gates check-secrets",
96
+ "check:ci-parity": "repo-gates check-ci-parity",
97
+ "check:coverage": "repo-gates check-coverage",
98
+ "format:check": "pnpm run format",
99
+ "check:agents": "repo-gates check-agents"
87
100
  },
88
101
  "dependencies": {
89
102
  "@stripe/connect-js": "^3.4.6",
@@ -95,6 +108,7 @@
95
108
  "devDependencies": {
96
109
  "@convex-dev/eslint-plugin": "^5.0.0",
97
110
  "@edge-runtime/vm": "^5.0.0",
111
+ "@fantastic.dev/repo-gates": "^0.4.0",
98
112
  "@testing-library/jest-dom": "^7.0.1",
99
113
  "@testing-library/react": "^16.3.3",
100
114
  "@testing-library/user-event": "^14.6.7",
@@ -113,7 +127,9 @@
113
127
  "pretty-quick": "^4.2.2",
114
128
  "typescript": "npm:@typescript/typescript6@^6.0.2",
115
129
  "typescript-eslint": "^8.71.1",
116
- "vitest": "^5.0.3"
130
+ "vitest": "^5.0.3",
131
+ "@shadcn/lint": "0.1.5",
132
+ "@shadscan/cli": "0.7.0"
117
133
  },
118
134
  "peerDependencies": {
119
135
  "convex": "^1.29.3",
@@ -0,0 +1,49 @@
1
+ import { expect, it, vi } from "vitest";
2
+ import type Stripe from "stripe";
3
+ import type { Component, RunCtx } from "../helpers.js";
4
+ import { createCheckoutSession } from "./checkout.js";
5
+ for (const [mode, expected] of [
6
+ ["custom", "elements"],
7
+ ["form", "form"],
8
+ ] as const)
9
+ it(`creates ${mode} checkout without hosted URLs`, async () => {
10
+ const create = vi.fn().mockResolvedValue({
11
+ id: "cs_test",
12
+ status: "open",
13
+ mode: "payment",
14
+ client_secret: "client_secret_test",
15
+ metadata: {},
16
+ expires_at: 1800000000,
17
+ });
18
+ const component = {
19
+ billing: {
20
+ mutations: {
21
+ upsertCheckoutSession: {
22
+ [Symbol.for("toReferencePath")]:
23
+ "betterStripe/billing/mutations/upsertCheckoutSession",
24
+ },
25
+ },
26
+ },
27
+ } as unknown as Component;
28
+ await createCheckoutSession(
29
+ { checkout: { sessions: { create } } } as unknown as Stripe,
30
+ component,
31
+ {
32
+ runQuery: vi.fn().mockResolvedValue(null),
33
+ runMutation: vi.fn(),
34
+ } as unknown as RunCtx,
35
+ {
36
+ userId: "user_1",
37
+ stripePriceId: "price_1",
38
+ mode: "payment",
39
+ uiMode: mode,
40
+ returnUrl: "https://app.test/return",
41
+ },
42
+ );
43
+ expect(create.mock.calls[0][0]).toMatchObject({
44
+ ui_mode: expected,
45
+ return_url: "https://app.test/return",
46
+ });
47
+ expect(create.mock.calls[0][0].success_url).toBeUndefined();
48
+ expect(create.mock.calls[0][0].cancel_url).toBeUndefined();
49
+ });
@@ -114,7 +114,7 @@ export async function createCheckoutSession(
114
114
  orgId?: string;
115
115
  stripePriceId: string;
116
116
  mode: "payment" | "subscription" | "setup";
117
- uiMode?: "embedded" | "redirect";
117
+ uiMode?: "embedded" | "redirect" | "custom" | "form";
118
118
  quantity?: number;
119
119
  returnUrl: string;
120
120
  trialDays?: number;
@@ -295,8 +295,13 @@ export async function createCheckoutSession(
295
295
  sessionParams.payment_intent_data = paymentIntentData;
296
296
  }
297
297
 
298
- if (uiMode === "embedded") {
299
- sessionParams.ui_mode = "embedded_page";
298
+ if (uiMode === "embedded" || uiMode === "custom" || uiMode === "form") {
299
+ sessionParams.ui_mode =
300
+ uiMode === "custom"
301
+ ? "elements"
302
+ : uiMode === "form"
303
+ ? "form"
304
+ : "embedded_page";
300
305
  sessionParams.return_url = opts.returnUrl;
301
306
  } else {
302
307
  sessionParams.success_url = `${opts.returnUrl}?session_id={CHECKOUT_SESSION_ID}`;
@@ -75,7 +75,9 @@ describe("listInvoices", () => {
75
75
 
76
76
  expect(result).toEqual([]);
77
77
  const [ref, args] = ctx.runQuery.mock.calls[0];
78
- expect(ref[TO_REF]).toBe(refPath(component, "billing/queries/listInvoices"));
78
+ expect(ref[TO_REF]).toBe(
79
+ refPath(component, "billing/queries/listInvoices"),
80
+ );
79
81
  expect(args).toEqual({});
80
82
  });
81
83
 
@@ -125,7 +127,9 @@ describe("listInvoicesByUser", () => {
125
127
 
126
128
  expect(result).toBe(rows);
127
129
  const [ref, args] = ctx.runQuery.mock.calls[0];
128
- expect(ref[TO_REF]).toBe(refPath(component, "billing/queries/listInvoices"));
130
+ expect(ref[TO_REF]).toBe(
131
+ refPath(component, "billing/queries/listInvoices"),
132
+ );
129
133
  expect(args).toEqual({ userId: "u_9" });
130
134
  });
131
135
  });
@@ -177,9 +181,9 @@ describe("upsertInvoice", () => {
177
181
  it("throws when ctx has no runMutation (runMutationOrThrow guard)", async () => {
178
182
  const ctx = { runQuery: vi.fn() } as unknown as RunCtx;
179
183
 
180
- await expect(
181
- upsertInvoice(makeComponent(), ctx, baseOpts),
182
- ).rejects.toThrow(/requires a Convex ctx with runMutation/);
184
+ await expect(upsertInvoice(makeComponent(), ctx, baseOpts)).rejects.toThrow(
185
+ /requires a Convex ctx with runMutation/,
186
+ );
183
187
  });
184
188
  });
185
189
 
@@ -189,7 +193,9 @@ describe("getInvoice", () => {
189
193
  const row = { stripeInvoiceId: "in_4", status: "paid" };
190
194
  const ctx = makeCtx(row);
191
195
 
192
- const result = await getInvoice(component, ctx, { stripeInvoiceId: "in_4" });
196
+ const result = await getInvoice(component, ctx, {
197
+ stripeInvoiceId: "in_4",
198
+ });
193
199
 
194
200
  expect(result).toBe(row);
195
201
  const [ref, args] = ctx.runQuery.mock.calls[0];
@@ -73,6 +73,21 @@ describe("buildDisputeEvidence (BTS-31)", () => {
73
73
  });
74
74
  });
75
75
 
76
+ it("sends communication prose as text while preserving other context", () => {
77
+ expect(
78
+ buildDisputeEvidence({
79
+ additionalInfo: "Delivered",
80
+ customerCommunication: "Customer confirmed receipt",
81
+ }),
82
+ ).toEqual({
83
+ uncategorized_text:
84
+ "Delivered\n\nCustomer communication:\nCustomer confirmed receipt",
85
+ });
86
+ expect(buildDisputeEvidence({ customerCommunication: "file_123" })).toEqual(
87
+ { customer_communication: "file_123" },
88
+ );
89
+ });
90
+
76
91
  it("omits unset categories", () => {
77
92
  expect(buildDisputeEvidence({ productDescription: "X" })).toEqual({
78
93
  product_description: "X",
@@ -260,9 +260,19 @@ export function buildDisputeEvidence(input: {
260
260
  accessActivity?: string;
261
261
  /** Off-platform context / anything else (Stripe: uncategorized_text). */
262
262
  additionalInfo?: string;
263
- /** Communications with the buyer (Stripe: customer_communication). */
263
+ /** Communication prose is appended to text evidence; file_ IDs remain file evidence. */
264
264
  customerCommunication?: string;
265
265
  }): import("stripe").Stripe.DisputeUpdateParams.Evidence {
266
+ const communication = input.customerCommunication;
267
+ const file = communication?.startsWith("file_") ? communication : undefined;
268
+ const text = [
269
+ input.additionalInfo,
270
+ !file && communication
271
+ ? `Customer communication:\n${communication}`
272
+ : undefined,
273
+ ]
274
+ .filter(Boolean)
275
+ .join("\n\n");
266
276
  return {
267
277
  ...(input.productDescription
268
278
  ? { product_description: input.productDescription }
@@ -270,12 +280,8 @@ export function buildDisputeEvidence(input: {
270
280
  ...(input.accessActivity
271
281
  ? { access_activity_log: input.accessActivity }
272
282
  : {}),
273
- ...(input.additionalInfo
274
- ? { uncategorized_text: input.additionalInfo }
275
- : {}),
276
- ...(input.customerCommunication
277
- ? { customer_communication: input.customerCommunication }
278
- : {}),
283
+ ...(text ? { uncategorized_text: text } : {}),
284
+ ...(file ? { customer_communication: file } : {}),
279
285
  };
280
286
  }
281
287
 
@@ -60,7 +60,9 @@ describe("payment methods are keyed to the customer_account (BTS-19 reuse)", ()
60
60
 
61
61
  it("detaches a payment method by id", async () => {
62
62
  const stripe = makeStripe();
63
- await detachPaymentMethod(asStripe(stripe), ctx, { paymentMethodId: "pm_1" });
63
+ await detachPaymentMethod(asStripe(stripe), ctx, {
64
+ paymentMethodId: "pm_1",
65
+ });
64
66
  expect(stripe.paymentMethods.detach).toHaveBeenCalledWith("pm_1");
65
67
  });
66
68
  });
@@ -51,5 +51,8 @@ export async function setDefaultPaymentMethod(
51
51
  _ctx: RunCtx,
52
52
  _opts: { stripeAccountId: string; paymentMethodId: string },
53
53
  ) {
54
- throwStripeError("PAYMENT_METHOD_FAILED", "[better-stripe] setDefaultPaymentMethod is not yet implemented for V2 Accounts. Use createBillingPortalSession() to let users manage payment methods.");
54
+ throwStripeError(
55
+ "PAYMENT_METHOD_FAILED",
56
+ "[better-stripe] setDefaultPaymentMethod is not yet implemented for V2 Accounts. Use createBillingPortalSession() to let users manage payment methods.",
57
+ );
55
58
  }
@@ -19,8 +19,7 @@ import type { SplitRecipientRole } from "../../component/lib/fees.js";
19
19
 
20
20
  /** Who is initiating a refund. `accountId` is the seller's `acct_…` id. */
21
21
  export type RefundActor =
22
- | { type: "admin" }
23
- | { type: "seller"; accountId: string };
22
+ { type: "admin" } | { type: "seller"; accountId: string };
24
23
 
25
24
  /**
26
25
  * The subset of a payment's routing needed to authorize a seller refund, read