@volter/twin-stripe 2.0.37 → 3.0.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 (442) hide show
  1. package/README.md +82 -207
  2. package/dist/generated/pack-facts.json +94 -0
  3. package/dist/spec/SOURCE.md +14 -0
  4. package/dist/spec/fixtures3.json.gz +0 -0
  5. package/dist/spec/openapi.json.gz +0 -0
  6. package/dist/spec/patches.json +34 -0
  7. package/dist/spec/sources.json +378 -0
  8. package/dist/src/cli.js +12 -30
  9. package/dist/src/engine/after-payment.d.ts +9 -0
  10. package/dist/src/engine/after-payment.js +28 -0
  11. package/dist/src/engine/apps-secrets.d.ts +1 -0
  12. package/dist/src/engine/apps-secrets.js +3 -0
  13. package/dist/src/engine/balance.d.ts +5 -0
  14. package/dist/src/engine/balance.js +15 -0
  15. package/dist/src/engine/billing.d.ts +5 -0
  16. package/dist/src/engine/billing.js +6 -0
  17. package/dist/src/engine/charges.d.ts +6 -0
  18. package/dist/src/engine/charges.js +13 -0
  19. package/dist/src/engine/checkout.d.ts +24 -0
  20. package/dist/src/engine/checkout.js +30 -0
  21. package/dist/src/engine/common.d.ts +19 -0
  22. package/dist/src/engine/common.js +32 -0
  23. package/dist/src/{screens → engine}/connect-settings.d.ts +1 -7
  24. package/dist/src/engine/connect-settings.js +26 -0
  25. package/dist/src/engine/connect.d.ts +66 -0
  26. package/dist/src/engine/connect.js +189 -0
  27. package/dist/src/engine/coupons.d.ts +0 -0
  28. package/dist/src/engine/coupons.js +5 -0
  29. package/dist/src/engine/credit-notes.d.ts +1 -0
  30. package/dist/src/engine/credit-notes.js +5 -0
  31. package/dist/src/engine/customers.d.ts +12 -0
  32. package/dist/src/engine/customers.js +30 -0
  33. package/dist/src/engine/display.d.ts +14 -0
  34. package/dist/src/engine/display.js +16 -0
  35. package/dist/src/engine/disputes.d.ts +0 -0
  36. package/dist/src/engine/disputes.js +9 -0
  37. package/dist/src/engine/entitlements.d.ts +1 -0
  38. package/dist/src/engine/entitlements.js +4 -0
  39. package/dist/src/engine/ephemeral-keys.d.ts +0 -0
  40. package/dist/src/engine/ephemeral-keys.js +4 -0
  41. package/dist/src/engine/files.d.ts +18 -0
  42. package/dist/src/engine/files.js +33 -0
  43. package/dist/src/engine/front.d.ts +5 -0
  44. package/dist/src/engine/front.js +25 -0
  45. package/dist/src/engine/invoices.d.ts +24 -0
  46. package/dist/src/engine/invoices.js +57 -0
  47. package/dist/src/engine/issuing.d.ts +35 -0
  48. package/dist/src/engine/issuing.js +45 -0
  49. package/dist/src/engine/ledger.d.ts +9 -0
  50. package/dist/src/engine/ledger.js +9 -0
  51. package/dist/src/engine/oauth.d.ts +4 -0
  52. package/dist/src/engine/oauth.js +25 -0
  53. package/dist/src/engine/onboarding.d.ts +13 -0
  54. package/dist/src/engine/onboarding.js +42 -0
  55. package/dist/src/{stripe-params.d.ts → engine/params.d.ts} +20 -3
  56. package/dist/src/{stripe-params.js → engine/params.js} +7 -60
  57. package/dist/src/engine/payment-intents.d.ts +10 -0
  58. package/dist/src/engine/payment-intents.js +27 -0
  59. package/dist/src/engine/payment-links.d.ts +1 -0
  60. package/dist/src/engine/payment-links.js +5 -0
  61. package/dist/src/engine/payment-methods.d.ts +16 -0
  62. package/dist/src/engine/payment-methods.js +22 -0
  63. package/dist/src/engine/plans.d.ts +6 -0
  64. package/dist/src/engine/plans.js +26 -0
  65. package/dist/src/engine/platform.d.ts +39 -0
  66. package/dist/src/engine/platform.js +34 -0
  67. package/dist/src/engine/products.d.ts +0 -0
  68. package/dist/src/engine/products.js +4 -0
  69. package/dist/src/engine/radar.d.ts +2 -0
  70. package/dist/src/engine/radar.js +5 -0
  71. package/dist/src/engine/refunds.d.ts +1 -0
  72. package/dist/src/engine/refunds.js +28 -0
  73. package/dist/src/engine/renewals.d.ts +36 -0
  74. package/dist/src/engine/renewals.js +65 -0
  75. package/dist/src/engine/setup-intents.d.ts +1 -0
  76. package/dist/src/engine/setup-intents.js +4 -0
  77. package/dist/src/{stripe-twin.d.ts → engine/stripe.d.ts} +11 -39
  78. package/dist/src/{stripe-twin.js → engine/stripe.js} +25 -310
  79. package/dist/src/engine/subscription-schedules.d.ts +3 -0
  80. package/dist/src/engine/subscription-schedules.js +1 -0
  81. package/dist/src/engine/subscriptions.d.ts +12 -0
  82. package/dist/src/engine/subscriptions.js +31 -0
  83. package/dist/src/engine/tax.d.ts +7 -0
  84. package/dist/src/engine/tax.js +28 -0
  85. package/dist/src/engine/terminal.d.ts +4 -0
  86. package/dist/src/engine/terminal.js +20 -0
  87. package/dist/src/engine/test-clocks.d.ts +5 -0
  88. package/dist/src/engine/test-clocks.js +9 -0
  89. package/dist/src/engine/tokens.d.ts +7 -0
  90. package/dist/src/engine/tokens.js +20 -0
  91. package/dist/src/engine/transfers.d.ts +2 -0
  92. package/dist/src/engine/transfers.js +1 -0
  93. package/dist/src/engine/treasury.d.ts +23 -0
  94. package/dist/src/engine/treasury.js +45 -0
  95. package/dist/src/{stripe-version.js → engine/version.js} +4 -3
  96. package/dist/src/engine/webhook-endpoints.d.ts +1 -0
  97. package/dist/src/engine/webhook-endpoints.js +12 -0
  98. package/dist/src/engine/webhooks.d.ts +31 -0
  99. package/dist/src/engine/webhooks.js +68 -0
  100. package/dist/src/fetch.d.ts +2 -0
  101. package/dist/src/fetch.js +26 -0
  102. package/dist/src/generated/surface.gen.json +1 -1
  103. package/dist/src/generated/ui.gen.json +1 -1
  104. package/dist/src/index.d.ts +5 -14
  105. package/dist/src/index.js +8 -75
  106. package/dist/src/manifest.js +232 -758
  107. package/dist/src/screens/billing-portal.d.ts +3 -0
  108. package/dist/src/screens/{portal.js → billing-portal.js} +28 -54
  109. package/dist/src/screens/checkout.d.ts +2 -31
  110. package/dist/src/screens/checkout.js +32 -121
  111. package/dist/src/screens/connect-oauth.d.ts +3 -27
  112. package/dist/src/screens/connect-oauth.js +51 -132
  113. package/dist/src/screens/connect-onboarding.d.ts +3 -0
  114. package/dist/src/screens/{onboarding.js → connect-onboarding.js} +36 -102
  115. package/dist/src/screens/dashboard.d.ts +3 -0
  116. package/dist/src/screens/dashboard.js +117 -0
  117. package/dist/src/screens/shared.d.ts +27 -0
  118. package/dist/src/screens/shared.js +87 -0
  119. package/dist/src/screens/stripe-js.d.ts +3 -0
  120. package/dist/src/screens/stripe-js.js +135 -0
  121. package/dist/src/semantics/account_links.d.ts +2 -0
  122. package/dist/src/semantics/account_links.js +22 -0
  123. package/dist/src/semantics/accounts.d.ts +4 -0
  124. package/dist/src/semantics/accounts.js +38 -0
  125. package/dist/src/semantics/apps.d.ts +4 -0
  126. package/dist/src/semantics/{apps-secrets.js → apps.js} +14 -26
  127. package/dist/src/semantics/around.d.ts +2 -0
  128. package/dist/src/semantics/around.js +16 -0
  129. package/dist/src/semantics/balance.d.ts +2 -11
  130. package/dist/src/semantics/balance.js +3 -194
  131. package/dist/src/semantics/balance_transactions.d.ts +2 -0
  132. package/dist/src/semantics/balance_transactions.js +15 -0
  133. package/dist/src/semantics/billing_portal.d.ts +5 -0
  134. package/dist/src/semantics/billing_portal.js +42 -0
  135. package/dist/src/semantics/charges.d.ts +3 -28
  136. package/dist/src/semantics/charges.js +5 -202
  137. package/dist/src/semantics/checkout.d.ts +3 -20
  138. package/dist/src/semantics/checkout.js +8 -261
  139. package/dist/src/semantics/clock.d.ts +2 -0
  140. package/dist/src/semantics/clock.js +21 -0
  141. package/dist/src/semantics/coupons.d.ts +2 -6
  142. package/dist/src/semantics/coupons.js +2 -60
  143. package/dist/src/semantics/customers.d.ts +6 -6
  144. package/dist/src/semantics/customers.js +27 -387
  145. package/dist/src/semantics/disputes.d.ts +2 -2
  146. package/dist/src/semantics/disputes.js +3 -49
  147. package/dist/src/semantics/doors.d.ts +23 -0
  148. package/dist/src/semantics/doors.js +73 -0
  149. package/dist/src/semantics/entitlements.d.ts +2 -2
  150. package/dist/src/semantics/entitlements.js +5 -50
  151. package/dist/src/semantics/events.d.ts +12 -0
  152. package/dist/src/semantics/events.js +36 -0
  153. package/dist/src/semantics/index.d.ts +2 -0
  154. package/dist/src/semantics/index.js +107 -0
  155. package/dist/src/semantics/invoice_payments.d.ts +2 -0
  156. package/dist/src/semantics/invoice_payments.js +12 -0
  157. package/dist/src/semantics/invoiceitems.d.ts +3 -0
  158. package/dist/src/semantics/invoiceitems.js +59 -0
  159. package/dist/src/semantics/invoices.d.ts +16 -18
  160. package/dist/src/semantics/invoices.js +118 -444
  161. package/dist/src/semantics/payment_intents.d.ts +4 -0
  162. package/dist/src/semantics/payment_intents.js +79 -0
  163. package/dist/src/semantics/payment_methods.d.ts +5 -0
  164. package/dist/src/semantics/payment_methods.js +39 -0
  165. package/dist/src/semantics/payouts.d.ts +2 -0
  166. package/dist/src/semantics/payouts.js +21 -0
  167. package/dist/src/semantics/prices.d.ts +4 -0
  168. package/dist/src/semantics/prices.js +37 -0
  169. package/dist/src/semantics/products.d.ts +6 -2
  170. package/dist/src/semantics/products.js +15 -130
  171. package/dist/src/semantics/promotion_codes.d.ts +3 -0
  172. package/dist/src/semantics/promotion_codes.js +35 -0
  173. package/dist/src/semantics/radar.d.ts +2 -2
  174. package/dist/src/semantics/radar.js +5 -74
  175. package/dist/src/semantics/refunds.d.ts +3 -9
  176. package/dist/src/semantics/refunds.js +6 -192
  177. package/dist/src/semantics/setup_intents.d.ts +3 -0
  178. package/dist/src/semantics/{setup-intents.js → setup_intents.js} +10 -53
  179. package/dist/src/semantics/shared.d.ts +822 -47
  180. package/dist/src/semantics/shared.js +3044 -78
  181. package/dist/src/semantics/states.d.ts +531 -0
  182. package/dist/src/semantics/states.js +852 -0
  183. package/dist/src/semantics/subscription_items.d.ts +5 -0
  184. package/dist/src/semantics/subscription_items.js +55 -0
  185. package/dist/src/semantics/subscription_schedules.d.ts +4 -0
  186. package/dist/src/semantics/subscription_schedules.js +60 -0
  187. package/dist/src/semantics/subscriptions.d.ts +7 -11
  188. package/dist/src/semantics/subscriptions.js +44 -415
  189. package/dist/src/semantics/test_helpers.d.ts +6 -0
  190. package/dist/src/semantics/{test-clocks.js → test_helpers.js} +14 -40
  191. package/dist/src/semantics/transfers.d.ts +2 -2
  192. package/dist/src/semantics/transfers.js +6 -101
  193. package/dist/src/server.d.ts +7 -0
  194. package/dist/src/server.js +7 -0
  195. package/generated/pack-facts.json +94 -0
  196. package/package.json +10 -20
  197. package/spec/SOURCE.md +14 -0
  198. package/spec/fixtures3.json.gz +0 -0
  199. package/spec/openapi.json.gz +0 -0
  200. package/spec/patches.json +34 -0
  201. package/spec/sources.json +378 -0
  202. package/src/cli.ts +12 -26
  203. package/src/engine/after-payment.ts +31 -0
  204. package/src/engine/apps-secrets.ts +4 -0
  205. package/src/engine/balance.ts +33 -0
  206. package/src/engine/billing.ts +16 -0
  207. package/src/engine/charges.ts +19 -0
  208. package/src/engine/checkout.ts +40 -0
  209. package/src/engine/common.ts +47 -0
  210. package/src/engine/connect-settings.ts +23 -0
  211. package/src/engine/connect.ts +184 -0
  212. package/src/engine/coupons.ts +5 -0
  213. package/src/engine/credit-notes.ts +6 -0
  214. package/src/engine/customers.ts +35 -0
  215. package/src/engine/display.ts +19 -0
  216. package/src/engine/disputes.ts +9 -0
  217. package/src/engine/entitlements.ts +5 -0
  218. package/src/engine/ephemeral-keys.ts +3 -0
  219. package/src/engine/files.ts +41 -0
  220. package/src/engine/front.ts +31 -0
  221. package/src/engine/invoices.ts +71 -0
  222. package/src/engine/issuing.ts +61 -0
  223. package/src/engine/ledger.ts +50 -0
  224. package/src/engine/oauth.ts +19 -0
  225. package/src/engine/onboarding.ts +54 -0
  226. package/src/{stripe-params.ts → engine/params.ts} +8 -56
  227. package/src/engine/payment-intents.ts +33 -0
  228. package/src/engine/payment-links.ts +6 -0
  229. package/src/engine/payment-methods.ts +25 -0
  230. package/src/engine/plans.ts +42 -0
  231. package/src/engine/platform.ts +47 -0
  232. package/src/engine/products.ts +3 -0
  233. package/src/engine/radar.ts +6 -0
  234. package/src/engine/refunds.ts +29 -0
  235. package/src/engine/renewals.ts +73 -0
  236. package/src/engine/setup-intents.ts +5 -0
  237. package/src/{stripe-twin.ts → engine/stripe.ts} +28 -323
  238. package/src/engine/subscription-schedules.ts +10 -0
  239. package/src/engine/subscriptions.ts +40 -0
  240. package/src/engine/tax.ts +39 -0
  241. package/src/engine/terminal.ts +23 -0
  242. package/src/engine/test-clocks.ts +11 -0
  243. package/src/engine/tokens.ts +22 -0
  244. package/src/engine/transfers.ts +23 -0
  245. package/src/engine/treasury.ts +47 -0
  246. package/src/{stripe-version.ts → engine/version.ts} +4 -3
  247. package/src/engine/webhook-endpoints.ts +14 -0
  248. package/src/engine/webhooks.ts +72 -0
  249. package/src/fetch.ts +27 -0
  250. package/src/generated/surface.gen.json +1 -1
  251. package/src/generated/ui.gen.json +1 -1
  252. package/src/index.ts +8 -116
  253. package/src/manifest.ts +234 -786
  254. package/src/screens/{portal.tsx → billing-portal.tsx} +32 -37
  255. package/src/screens/checkout.tsx +33 -95
  256. package/src/screens/connect-oauth.tsx +64 -88
  257. package/src/screens/{onboarding.tsx → connect-onboarding.tsx} +38 -82
  258. package/src/screens/dashboard.tsx +198 -0
  259. package/src/screens/shared.tsx +84 -0
  260. package/src/screens/stripe-js.ts +170 -0
  261. package/src/semantics/account_links.ts +21 -0
  262. package/src/semantics/accounts.ts +43 -0
  263. package/src/semantics/{apps-secrets.ts → apps.ts} +17 -32
  264. package/src/semantics/around.ts +20 -0
  265. package/src/semantics/balance.ts +6 -207
  266. package/src/semantics/balance_transactions.ts +20 -0
  267. package/src/semantics/billing_portal.ts +51 -0
  268. package/src/semantics/charges.ts +12 -211
  269. package/src/semantics/checkout.ts +13 -268
  270. package/src/semantics/clock.ts +26 -0
  271. package/src/semantics/coupons.ts +5 -67
  272. package/src/semantics/customers.ts +29 -392
  273. package/src/semantics/disputes.ts +9 -59
  274. package/src/semantics/doors.ts +80 -0
  275. package/src/semantics/entitlements.ts +9 -56
  276. package/src/semantics/events.ts +44 -0
  277. package/src/semantics/index.ts +111 -0
  278. package/src/semantics/invoice_payments.ts +18 -0
  279. package/src/semantics/invoiceitems.ts +59 -0
  280. package/src/semantics/invoices.ts +109 -443
  281. package/src/semantics/payment_intents.ts +83 -0
  282. package/src/semantics/payment_methods.ts +43 -0
  283. package/src/semantics/payouts.ts +23 -0
  284. package/src/semantics/prices.ts +42 -0
  285. package/src/semantics/products.ts +18 -142
  286. package/src/semantics/promotion_codes.ts +39 -0
  287. package/src/semantics/radar.ts +8 -77
  288. package/src/semantics/refunds.ts +9 -212
  289. package/src/semantics/setup_intents.ts +45 -0
  290. package/src/semantics/shared.ts +3092 -106
  291. package/src/semantics/states.ts +883 -0
  292. package/src/semantics/subscription_items.ts +54 -0
  293. package/src/semantics/subscription_schedules.ts +66 -0
  294. package/src/semantics/subscriptions.ts +49 -432
  295. package/src/semantics/{test-clocks.ts → test_helpers.ts} +23 -47
  296. package/src/semantics/transfers.ts +11 -131
  297. package/src/server.ts +8 -0
  298. package/client/dashboard-api.ts +0 -286
  299. package/client/stripe-mirror.css +0 -277
  300. package/client/stripe-mirror.tsx +0 -1559
  301. package/dist/client/dashboard-api.d.ts +0 -107
  302. package/dist/client/dashboard-api.js +0 -238
  303. package/dist/client/dashboard-api.ts +0 -286
  304. package/dist/client/stripe-mirror.bundle.js +0 -236
  305. package/dist/client/stripe-mirror.css +0 -277
  306. package/dist/client/stripe-mirror.d.ts +0 -134
  307. package/dist/client/stripe-mirror.js +0 -859
  308. package/dist/client/stripe-mirror.tsx +0 -1559
  309. package/dist/src/screens/connect-settings.js +0 -103
  310. package/dist/src/screens/consent-skin.d.ts +0 -4
  311. package/dist/src/screens/consent-skin.js +0 -18
  312. package/dist/src/screens/financial-connections.d.ts +0 -5
  313. package/dist/src/screens/financial-connections.js +0 -90
  314. package/dist/src/screens/identity.d.ts +0 -5
  315. package/dist/src/screens/identity.js +0 -86
  316. package/dist/src/screens/onboarding.d.ts +0 -13
  317. package/dist/src/screens/portal.d.ts +0 -5
  318. package/dist/src/screens/public-details.d.ts +0 -5
  319. package/dist/src/screens/public-details.js +0 -90
  320. package/dist/src/semantics/after-payment.d.ts +0 -22
  321. package/dist/src/semantics/after-payment.js +0 -99
  322. package/dist/src/semantics/apps-secrets.d.ts +0 -2
  323. package/dist/src/semantics/billing.d.ts +0 -2
  324. package/dist/src/semantics/billing.js +0 -220
  325. package/dist/src/semantics/connect.d.ts +0 -5
  326. package/dist/src/semantics/connect.js +0 -493
  327. package/dist/src/semantics/credit-notes.d.ts +0 -2
  328. package/dist/src/semantics/credit-notes.js +0 -172
  329. package/dist/src/semantics/ephemeral-keys.d.ts +0 -2
  330. package/dist/src/semantics/ephemeral-keys.js +0 -34
  331. package/dist/src/semantics/files.d.ts +0 -2
  332. package/dist/src/semantics/files.js +0 -125
  333. package/dist/src/semantics/issuing.d.ts +0 -13
  334. package/dist/src/semantics/issuing.js +0 -575
  335. package/dist/src/semantics/ledger.d.ts +0 -59
  336. package/dist/src/semantics/ledger.js +0 -200
  337. package/dist/src/semantics/payment-intents.d.ts +0 -18
  338. package/dist/src/semantics/payment-intents.js +0 -452
  339. package/dist/src/semantics/payment-links.d.ts +0 -2
  340. package/dist/src/semantics/payment-links.js +0 -133
  341. package/dist/src/semantics/payment-methods.d.ts +0 -20
  342. package/dist/src/semantics/payment-methods.js +0 -140
  343. package/dist/src/semantics/plans.d.ts +0 -5
  344. package/dist/src/semantics/plans.js +0 -121
  345. package/dist/src/semantics/platform.d.ts +0 -9
  346. package/dist/src/semantics/platform.js +0 -206
  347. package/dist/src/semantics/renewals.d.ts +0 -47
  348. package/dist/src/semantics/renewals.js +0 -281
  349. package/dist/src/semantics/setup-intents.d.ts +0 -2
  350. package/dist/src/semantics/subscription-schedules.d.ts +0 -2
  351. package/dist/src/semantics/subscription-schedules.js +0 -119
  352. package/dist/src/semantics/tax.d.ts +0 -2
  353. package/dist/src/semantics/tax.js +0 -197
  354. package/dist/src/semantics/terminal.d.ts +0 -5
  355. package/dist/src/semantics/terminal.js +0 -182
  356. package/dist/src/semantics/test-clocks.d.ts +0 -6
  357. package/dist/src/semantics/tokens.d.ts +0 -4
  358. package/dist/src/semantics/tokens.js +0 -44
  359. package/dist/src/semantics/treasury.d.ts +0 -2
  360. package/dist/src/semantics/treasury.js +0 -377
  361. package/dist/src/semantics/webhook-endpoints.d.ts +0 -3
  362. package/dist/src/semantics/webhook-endpoints.js +0 -85
  363. package/dist/src/stripe-budget.d.ts +0 -55
  364. package/dist/src/stripe-budget.js +0 -155
  365. package/dist/src/stripe-capabilities.d.ts +0 -3
  366. package/dist/src/stripe-capabilities.js +0 -5836
  367. package/dist/src/stripe-conformance.d.ts +0 -43
  368. package/dist/src/stripe-conformance.js +0 -105
  369. package/dist/src/stripe-connector.d.ts +0 -161
  370. package/dist/src/stripe-connector.js +0 -414
  371. package/dist/src/stripe-emit.d.ts +0 -2
  372. package/dist/src/stripe-emit.js +0 -145
  373. package/dist/src/stripe-events.d.ts +0 -93
  374. package/dist/src/stripe-events.js +0 -392
  375. package/dist/src/stripe-js.d.ts +0 -4
  376. package/dist/src/stripe-js.js +0 -70
  377. package/dist/src/stripe-mirror-ui.d.ts +0 -15
  378. package/dist/src/stripe-mirror-ui.js +0 -87
  379. package/dist/src/stripe-perform-harness.d.ts +0 -9
  380. package/dist/src/stripe-perform-harness.js +0 -26
  381. package/dist/src/stripe-server.d.ts +0 -33
  382. package/dist/src/stripe-server.js +0 -429
  383. package/dist/src/stripe-shared.d.ts +0 -109
  384. package/dist/src/stripe-shared.js +0 -276
  385. package/dist/src/stripe-ui-conformance.d.ts +0 -5
  386. package/dist/src/stripe-ui-conformance.js +0 -79
  387. package/dist/src/stripe-ui-structure.d.ts +0 -3
  388. package/dist/src/stripe-ui-structure.js +0 -168
  389. package/dist/test-fixtures/stripe-known-deviations.json +0 -110
  390. package/dist/test-fixtures/stripe-openapi-operations.SOURCE.md +0 -14
  391. package/dist/test-fixtures/stripe-openapi-operations.json +0 -4717
  392. package/dist/test-fixtures/stripe-schemas.SOURCE.md +0 -35
  393. package/dist/test-fixtures/stripe-schemas.json +0 -3813
  394. package/src/screens/connect-settings.tsx +0 -121
  395. package/src/screens/consent-skin.ts +0 -20
  396. package/src/screens/financial-connections.tsx +0 -101
  397. package/src/screens/identity.tsx +0 -96
  398. package/src/screens/public-details.tsx +0 -105
  399. package/src/semantics/after-payment.ts +0 -118
  400. package/src/semantics/billing.ts +0 -216
  401. package/src/semantics/connect.ts +0 -487
  402. package/src/semantics/credit-notes.ts +0 -168
  403. package/src/semantics/ephemeral-keys.ts +0 -34
  404. package/src/semantics/files.ts +0 -143
  405. package/src/semantics/issuing.ts +0 -590
  406. package/src/semantics/ledger.ts +0 -253
  407. package/src/semantics/payment-intents.ts +0 -463
  408. package/src/semantics/payment-links.ts +0 -148
  409. package/src/semantics/payment-methods.ts +0 -145
  410. package/src/semantics/plans.ts +0 -131
  411. package/src/semantics/platform.ts +0 -220
  412. package/src/semantics/renewals.ts +0 -279
  413. package/src/semantics/setup-intents.ts +0 -87
  414. package/src/semantics/subscription-schedules.ts +0 -129
  415. package/src/semantics/tax.ts +0 -220
  416. package/src/semantics/terminal.ts +0 -195
  417. package/src/semantics/tokens.ts +0 -52
  418. package/src/semantics/treasury.ts +0 -383
  419. package/src/semantics/webhook-endpoints.ts +0 -87
  420. package/src/stripe-budget.ts +0 -181
  421. package/src/stripe-capabilities.ts +0 -5651
  422. package/src/stripe-conformance.ts +0 -124
  423. package/src/stripe-connector.ts +0 -462
  424. package/src/stripe-emit.ts +0 -157
  425. package/src/stripe-events.ts +0 -434
  426. package/src/stripe-js.ts +0 -70
  427. package/src/stripe-mirror-ui.ts +0 -90
  428. package/src/stripe-perform-harness.ts +0 -29
  429. package/src/stripe-server.ts +0 -393
  430. package/src/stripe-shared.ts +0 -297
  431. package/src/stripe-ui-conformance.ts +0 -88
  432. package/src/stripe-ui-structure.ts +0 -182
  433. package/test-fixtures/stripe-known-deviations.json +0 -110
  434. package/test-fixtures/stripe-openapi-operations.json +0 -4717
  435. package/test-fixtures/stripe-schemas.json +0 -3813
  436. /package/dist/src/{screens → engine}/industries.d.ts +0 -0
  437. /package/dist/src/{screens → engine}/industries.js +0 -0
  438. /package/dist/src/{semantics → engine}/test-cards.d.ts +0 -0
  439. /package/dist/src/{semantics → engine}/test-cards.js +0 -0
  440. /package/dist/src/{stripe-version.d.ts → engine/version.d.ts} +0 -0
  441. /package/src/{screens → engine}/industries.ts +0 -0
  442. /package/src/{semantics → engine}/test-cards.ts +0 -0
@@ -1,209 +1,8 @@
1
- // Balance and payout semantics. The balance is computed from the balance-transaction ledger (./ledger.ts), never
2
- // stored: funds past their available_on are available, the rest pending, and Issuing funds their own section. The
3
- // balance, the payouts and the ledger are the acting account's: the platform's, or a connected account's under the
4
- // Stripe-Account header. A payout comes out of what that account has available and goes to its bank account, which a
5
- // connected account must have (docs.stripe.com/connect/payouts-connected-accounts). A pending payout can be canceled,
6
- // which returns its money; a connected account's paid payout can be reversed, which debits its bank account back
7
- // into its balance (docs.stripe.com/api/payouts/reverse). The machine in ../manifest.ts says how a payout's status
8
- // moves.
9
- //
10
- // Stripe also pays each account out on its own schedule (settings.payouts.schedule: daily by default, weekly or monthly
11
- // on an anchor, or manual): an automatic payout takes what has become available since the last one, and the ledger
12
- // lists the entries it paid (docs.stripe.com/payouts#payout-schedule, docs.stripe.com/connect/manage-payout-schedule).
13
- // A connected account is paid out once it can be (payouts_enabled, with a bank account).
14
- //
15
- // Where the documentation stops and the twin decides: a payout arrives two days after it is made (Stripe's standard
16
- // US schedule counts business days) and reads paid from then on; an automatic payout is made at midnight UTC on the
17
- // first scheduled day on or after its funds become available, only when what it would pay is positive.
18
- import type { Semantics, SemanticsContext } from '@volter/world-core';
19
- import { validateMoney } from '../stripe-twin.ts';
20
- import { accountSettings, PLATFORM_ACCOUNT_ID } from '../stripe-twin.ts';
21
- import { actingAccount, balanceOf, refusePayout, settleAutomaticPayout, settlePayout, unpaidEntries } from './ledger.ts';
22
- import { at, at_, created, fail, inRange, list, newest, send, where, type Row, kept } from './shared.ts';
1
+ // Stripe's balance operations (docs/contributing/architecture.md, "What an author writes"): each handler over the
2
+ // handler contract's context, computing with the engine (../engine/).
3
+ import type { HandlerContext } from '@volter/world-core';
4
+ import { balanceBody } from './shared.ts';
23
5
 
24
- const account = actingAccount;
25
- const DAY = 86_400;
26
- const payoutMissing = (ctx: SemanticsContext, id: string): Response => fail(ctx, `No such payout: '${id}'`, 404, 'resource_missing');
27
-
28
- /** The acting account's Balance object (docs.stripe.com/api/balance/balance_object). */
29
- export function balanceBody(ctx: SemanticsContext): Row {
30
- const { available, pending, issuing } = balanceOf(ctx);
31
- const toArr = (m: Map<string, number>) => {
32
- const out = [...m.entries()].map(([currency, amount]) => ({ amount, currency, source_types: { card: amount } }));
33
- return out.length ? out : [{ amount: 0, currency: 'usd', source_types: { card: 0 } }];
34
- };
35
- // a platform's balance holds its connected accounts' reserve, "Funds held due to negative balances on connected accounts
36
- // where account.controller.requirement_collection is `application`" (docs.stripe.com/api/balance/balance_object, whose
37
- // example answers `[{"amount": 0, "currency": "usd"}]`); the twin models no such reserve, so it is zero in each currency
38
- const reserved = account(ctx) ? {} : { connect_reserved: toArr(available).map((b) => ({ amount: 0, currency: b.currency })) };
39
- return {
40
- object: 'balance', available: toArr(available), pending: toArr(pending), ...reserved, livemode: false,
41
- ...(issuing.size ? { issuing: { available: [...issuing.entries()].map(([currency, amount]) => ({ amount, currency, source_types: { card: amount } })) } } : {}),
42
- };
43
- }
44
-
45
- const balance: Semantics = async (ctx) => ctx.reply(balanceBody(ctx));
46
-
47
- /** Time's arrivals, written: each of the acting account's payouts whose arrival date has come moves pending → paid
48
- * (the clock's move, as asOf reads it), written as `payout.paid`, the event Stripe sends for it. Answers their ids. */
49
- export async function payDuePayouts(ctx: SemanticsContext): Promise<string[]> {
50
- const acct = account(ctx);
51
- const now = Number(ctx.now());
52
- const paid: string[] = [];
53
- for (const p of newest(ctx, 'payout')) {
54
- if ((acct ? kept(ctx, 'payout', p, '_account') !== acct : !!kept(ctx, 'payout', p, '_account')) || p.status !== 'pending' || Number(p.arrival_date) > now) continue;
55
- if (ctx.legal('payout', 'status', ctx.call.operation.id, 'pending', 'paid', String(p.id), 'time')) continue;
56
- await ctx.write('payout', String(p.id), { status: 'paid' }, 'payout.paid');
57
- paid.push(String(p.id));
58
- }
59
- return paid;
60
- }
61
-
62
- /** Where a connected account's payout goes: "ID of the bank account or card the payout is sent to" (served spec,
63
- * payout.destination), its default external account for the currency, "When multiple accounts are available for a given
64
- * currency, Stripe uses the one set as `default_for_currency`" (docs.stripe.com/connect/payouts-bank-accounts), the
65
- * newest such. Where the documentation stops and the twin decides: the platform's own bank account is not modelled, so
66
- * its payouts name none. */
67
- function payoutBank(ctx: SemanticsContext, account: string, currency: string): string | null {
68
- const banks = newest(ctx, 'external_account').filter((e) => e.account === account && String(e.currency ?? currency) === currency);
69
- return String((banks.find((e) => e.default_for_currency === true) ?? banks[0])?.id ?? '') || null;
70
- }
71
-
72
- const payoutDefaults = (ctx: SemanticsContext): Row => ({
73
- method: 'standard', type: 'bank_account', source_type: 'card', automatic: false,
74
- reconciliation_status: 'not_applicable', arrival_date: Number(ctx.now()) + 2 * DAY, livemode: false, metadata: {},
75
- });
76
-
77
- /** A payout as the clock reads it: paid once its arrival date has come, the clock's move, asked of the
78
- * machine as a write asks it. */
79
- function asOf(ctx: SemanticsContext, p: Row): Row {
80
- if (p.status !== 'pending' || Number(p.arrival_date) > Number(ctx.now())) return p;
81
- ctx.legal('payout', 'status', ctx.call.operation.id, 'pending', 'paid', String(p.id), 'time');
82
- return { ...p, status: 'paid' };
83
- }
84
-
85
- /** A connected account's payout in a currency none of its bank accounts takes. */
86
- function noExternalAccount(ctx: SemanticsContext, currency: string): Response {
87
- return fail(ctx, `Sorry, you don't have any external accounts in that currency (${currency}).`, 400);
6
+ export async function GetBalance(ctx: HandlerContext): Promise<Response> {
7
+ return ctx.reply(balanceBody(ctx));
88
8
  }
89
-
90
- const createPayout: Semantics = async (ctx) => {
91
- const bad = validateMoney(ctx.params);
92
- if (bad) return send(ctx, bad);
93
- const acct = account(ctx);
94
- if (acct && !ctx.get('account', acct)) return fail(ctx, `No such account: '${acct}'`, 400, 'account_invalid');
95
- const amount = Math.trunc(Number(ctx.params.amount) || 0);
96
- const currency = String(ctx.params.currency ?? 'usd');
97
- // a connected account is paid out to its own bank account
98
- if (acct && !ctx.rows('external_account').some((e) => e.account === acct && (e.currency ?? currency) === currency)) return noExternalAccount(ctx, currency);
99
- const refused = refusePayout(ctx, amount, currency);
100
- if (refused) return refused;
101
- const id = ctx.mint('payout');
102
- const bt = await settlePayout(ctx, id, -amount, currency);
103
- return ctx.reply(await created(ctx, 'payout', { ...ctx.params, id }, { status: 'pending', ...payoutDefaults(ctx), balance_transaction: bt, destination: acct ? payoutBank(ctx, acct, currency) : null, ...(acct ? { _account: acct } : {}) }));
104
- };
105
-
106
- const listPayouts: Semantics = async (ctx) => {
107
- const acct = account(ctx);
108
- const scoped = newest(ctx, 'payout').filter((p) => (acct ? kept(ctx, 'payout', p, '_account') === acct : !kept(ctx, 'payout', p, '_account'))).map((p) => asOf(ctx, p));
109
- return list(ctx, 'payout', where(ctx, scoped, { status: (p, v) => p.status === v, created: (p, v) => inRange(p.created, v), arrival_date: (p, v) => inRange(p.arrival_date, v) }));
110
- };
111
-
112
- const DAYS = ['sunday', 'monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday'];
113
- /** The first scheduled payout time on or after `from`: midnight UTC of a day the schedule pays out on. */
114
- function payoutDay(from: number, schedule: Row): number {
115
- const first = Math.ceil(from / DAY) * DAY;
116
- const pays = (day: number): boolean => {
117
- const d = new Date(day * 1000);
118
- if (schedule.interval === 'weekly') return DAYS[d.getUTCDay()] === String(schedule.weekly_anchor ?? 'monday');
119
- if (schedule.interval === 'monthly') return d.getUTCDate() === Math.min(Number(schedule.monthly_anchor ?? 1), new Date(Date.UTC(d.getUTCFullYear(), d.getUTCMonth() + 1, 0)).getUTCDate());
120
- return true;
121
- };
122
- return Array.from({ length: 62 }, (_, i) => first + i * DAY).find(pays) ?? first;
123
- }
124
-
125
- /** Time's payouts, caught up to the World's clock: each account on an automatic schedule is paid out, on each of its
126
- * scheduled days that has come, what became available by then. */
127
- export async function advancePayouts(ctx: SemanticsContext): Promise<void> {
128
- const now = Number(ctx.now());
129
- const platform = ctx.get('account', PLATFORM_ACCOUNT_ID);
130
- const accounts: Array<{ id: string | undefined; settings: unknown }> = [{ id: undefined, settings: platform?.settings }];
131
- for (const a of ctx.rows('account')) {
132
- if (a.id === PLATFORM_ACCOUNT_ID || a.payouts_enabled !== true) continue;
133
- if (!ctx.rows('external_account').some((e) => e.account === a.id)) continue;
134
- accounts.push({ id: String(a.id), settings: a.settings });
135
- }
136
- for (const acct of accounts) {
137
- const schedule = ((accountSettings(acct.settings, (acct.settings as Row | undefined) ?? undefined).payouts as Row).schedule ?? {}) as Row;
138
- if (schedule.interval === 'manual') continue;
139
- const unpaid = unpaidEntries(ctx, acct.id);
140
- const days = [...new Set(unpaid.map((t) => payoutDay(Number(t.available_on) || 0, schedule)))].filter((d) => d <= now).sort((x, y) => x - y);
141
- const paid = new Set<unknown>();
142
- for (const day of days) {
143
- const due = unpaid.filter((t) => !paid.has(t.id) && (Number(t.available_on) || 0) <= day);
144
- const byCurrency = new Map<string, Row[]>();
145
- for (const t of due) byCurrency.set(String(t.currency ?? 'usd'), [...(byCurrency.get(String(t.currency ?? 'usd')) ?? []), t]);
146
- for (const [currency, entries] of byCurrency) {
147
- const amount = entries.reduce((n, t) => n + (Number(t.net) || 0), 0);
148
- // nothing to pay yet: what came due is carried to the next payout
149
- if (amount <= 0) continue;
150
- // made on its day, as Stripe makes it, whenever the request that catches it up comes
151
- const c = await at_(ctx)(day);
152
- const id = c.mint('payout');
153
- const bt = await settleAutomaticPayout(c, id, amount, currency, acct.id, day, entries);
154
- await created(c, 'payout', { id, amount, currency }, {
155
- status: 'pending', ...payoutDefaults(c), arrival_date: day + 2 * DAY, automatic: true, balance_transaction: bt, destination: acct.id ? payoutBank(c, String(acct.id), currency) : null,
156
- description: 'STRIPE PAYOUT', ...(acct.id ? { _account: acct.id } : {}),
157
- });
158
- for (const t of entries) paid.add(t.id);
159
- }
160
- }
161
- }
162
- }
163
-
164
- const retrievePayout: Semantics = async (ctx) => {
165
- const p = ctx.get('payout', at(ctx, 'payout'));
166
- return p ? ctx.reply(asOf(ctx, p)) : payoutMissing(ctx, at(ctx, 'payout'));
167
- };
168
-
169
- const cancelPayout: Semantics = async (ctx) => {
170
- const id = at(ctx, 'payout');
171
- const po = ctx.get('payout', id);
172
- if (!po) return payoutMissing(ctx, id);
173
- const refused = ctx.legal('payout', 'status', 'PostPayoutsPayoutCancel', asOf(ctx, po).status, undefined, id);
174
- if (refused) return ctx.refuse(refused);
175
- // the money comes back to the balance it left
176
- const owner = kept(ctx, 'payout', po, '_account');
177
- await settlePayout(ctx, id, Number(po.amount) || 0, String(po.currency ?? 'usd'), typeof owner === 'string' ? owner : null);
178
- return ctx.reply(await ctx.write('payout', id, { status: 'canceled' }, 'payout.cancel'));
179
- };
180
-
181
- // a reversal is itself a payout in the other direction, back into the connected account's balance, as the reverse page's
182
- // example answers it: a negative amount, pending until it arrives, carrying the request's metadata
183
- // (docs.stripe.com/api/payouts/reverse); the original stays paid and names it
184
- const reversePayout: Semantics = async (ctx) => {
185
- const id = at(ctx, 'payout');
186
- const po = ctx.get('payout', id);
187
- if (!po) return payoutMissing(ctx, id);
188
- const owner = kept(ctx, 'payout', po, '_account');
189
- if (typeof owner !== 'string') return fail(ctx, "Payout reversals are only supported for payouts to connected accounts' bank accounts.", 400);
190
- const status = String(asOf(ctx, po).status);
191
- if (po.reversed_by || status !== 'paid') return ctx.refuse({ status: 400, code: 'payout_reversal_not_allowed', message: po.reversed_by ? 'This payout has already been reversed.' : `This payout cannot be reversed because it has a status of ${status}. A pending payout can be canceled instead.` });
192
- const reversalId = ctx.mint('payout');
193
- const bt = await settlePayout(ctx, reversalId, Number(po.amount) || 0, String(po.currency ?? 'usd'), owner);
194
- const metadata = ctx.params.metadata && typeof ctx.params.metadata === 'object' ? { metadata: ctx.params.metadata } : {};
195
- const reversal = await created(ctx, 'payout', { id: reversalId, amount: -(Number(po.amount) || 0), currency: po.currency, ...metadata }, {
196
- status: 'pending', ...payoutDefaults(ctx), balance_transaction: bt, original_payout: id, destination: po.destination ?? null, _account: owner,
197
- });
198
- await ctx.write('payout', id, { reversed_by: reversal.id }, 'payout.reversed');
199
- return ctx.reply(reversal);
200
- };
201
-
202
- export const balances: Record<string, Semantics> = {
203
- GetBalance: balance,
204
- PostPayouts: createPayout,
205
- GetPayouts: listPayouts,
206
- GetPayoutsPayout: retrievePayout,
207
- PostPayoutsPayoutCancel: cancelPayout,
208
- PostPayoutsPayoutReverse: reversePayout,
209
- };
@@ -0,0 +1,20 @@
1
+ // Stripe's balance_transactions operations (docs/contributing/architecture.md, "What an author writes"): each handler over the
2
+ // handler contract's context, computing with the engine (../engine/).
3
+ import type { HandlerContext } from '@volter/world-core';
4
+ import { inRange } from '../engine/common.ts';
5
+ import { BT } from '../engine/ledger.ts';
6
+ import { at, commonAsOf, kept, list, mine, newest, where } from './shared.ts';
7
+
8
+ export async function GetBalanceTransactions(ctx: HandlerContext): Promise<Response> {
9
+ const own = mine(ctx);
10
+ return list(ctx, BT, where(ctx, newest(ctx, BT).filter((t) => own.has(t.id)).map((t) => commonAsOf(ctx, t)), {
11
+ type: (t, v) => t.type === v,
12
+ currency: (t, v) => t.currency === v,
13
+ source: (t, v) => t.source === v,
14
+ // an automatic payout lists the entries it paid out, its own debit among them
15
+ payout: (t, v) => t.source === v || kept(ctx, BT, t, '_payout') === v,
16
+ // a range of creation times (docs.stripe.com/api/balance_transactions/list#balance_transaction_list-created)
17
+ created: (t, v) => inRange(t.created, v),
18
+ }));
19
+ }
20
+
@@ -0,0 +1,51 @@
1
+ // Stripe's billing_portal operations (docs/contributing/architecture.md, "What an author writes"): each handler over the
2
+ // handler contract's context, computing with the engine (../engine/).
3
+ import type { HandlerContext } from '@volter/world-core';
4
+ import { filled, PBC, PORTAL_FEATURES } from '../engine/files.ts';
5
+ import { asBool, nowUnix } from '../engine/stripe.ts';
6
+ import { actingAccount, at, created, fail, list, mergeUpdate, newest, where } from './shared.ts';
7
+
8
+ export async function GetBillingPortalConfigurations(ctx: HandlerContext): Promise<Response> {
9
+ return list(ctx, PBC, where(ctx, newest(ctx, PBC), {
10
+ active: (c, v) => asBool(c.active) === asBool(v),
11
+ is_default: (c, v) => asBool(c.is_default) === asBool(v),
12
+ }));
13
+ }
14
+
15
+ export async function PostBillingPortalConfigurations(ctx: HandlerContext): Promise<Response> {
16
+ return ctx.reply(
17
+ await created(ctx, PBC, { ...ctx.params, business_profile: filled({ headline: null, privacy_policy_url: null, terms_of_service_url: null }, ctx.params.business_profile), features: filled(PORTAL_FEATURES, ctx.params.features) }, {
18
+ active: true, is_default: false, livemode: false,
19
+ login_page: { enabled: false, url: null },
20
+ metadata: {}, default_return_url: ctx.params.default_return_url ?? null,
21
+ updated: nowUnix(ctx.occurredAt),
22
+ }),
23
+ );
24
+ }
25
+
26
+ export async function PostBillingPortalConfigurationsConfiguration(ctx: HandlerContext): Promise<Response> {
27
+ const id = at(ctx, 'configuration');
28
+ if (!ctx.get(PBC, id)) return ctx.notFound(PBC, id);
29
+ return ctx.reply(await ctx.write(PBC, id, mergeUpdate(ctx, PBC, id, { ...ctx.params, updated: nowUnix(ctx.occurredAt) }), 'billing_portal.configuration.update'));
30
+ }
31
+
32
+ // ── the customer portal ──
33
+
34
+ // the configuration defaults to the account's default one
35
+ export async function PostBillingPortalSessions(ctx: HandlerContext): Promise<Response> {
36
+ const customer = typeof ctx.params.customer === 'string' ? ctx.params.customer : '';
37
+ if (!customer) return fail(ctx, 'Missing required param: customer.', 400, 'parameter_missing');
38
+ if (!ctx.row('customer', customer, { withDeleted: true })) return fail(ctx, `No such customer: '${customer}'`, 404, 'resource_missing');
39
+ const configuration = typeof ctx.params.configuration === 'string' && ctx.params.configuration
40
+ ? ctx.params.configuration
41
+ : (ctx.rowsRaw('billing_portal.configuration', { withDeleted: true }).find((c) => c.is_default)?.id ?? 'bpc_twin_default');
42
+ const id = ctx.mint('billing_portal.session');
43
+ return ctx.reply(
44
+ await created(ctx, 'billing_portal.session', {
45
+ id, customer, configuration, return_url: ctx.params.return_url ?? null, url: `https://billing.stripe.com/p/session/${id}`,
46
+ locale: ctx.params.locale ?? null, on_behalf_of: ctx.params.on_behalf_of ?? null, livemode: false,
47
+ // the account the session was made on (Stripe-Account), whose name the portal shows (screens/billing-portal.tsx)
48
+ ...(actingAccount(ctx) ? { _brand_account: actingAccount(ctx) } : {}),
49
+ }, {}),
50
+ );
51
+ }
@@ -1,220 +1,21 @@
1
- // Charge semantics. The machine in ../manifest.ts says a charge is captured once; these handlers
2
- // compute the money: a charge's `refunds` sub-list is derived on every read from the refunds that
3
- // point at it, never a stored snapshot, while the cumulative `amount_refunded` / `refunded` stay
4
- // stored (a partial capture moves them for a reason that is also a Refund row).
5
- import type { Semantics, SemanticsContext } from '@volter/world-core';
6
- import { asBool, cardError, chargeDefaults, declineFor, searchOver, validateMoney } from '../stripe-twin.ts';
7
- import { afterCharge } from './after-payment.ts';
8
- import { settleCharge } from './ledger.ts';
9
- import { paymentMethodDetails } from './payment-methods.ts';
10
- import { refundCharge } from './refunds.ts';
11
- import { at, created, expanded, fail, finder, list, newest, path, refundDestination, send, where, type Row } from './shared.ts';
12
-
13
- const chargeMissing = (ctx: SemanticsContext, id: string): Response => fail(ctx, `No such charge: '${id}'`, 404, 'resource_missing');
14
-
15
- /** Every egress of a charge carries its refunds, derived from the refund rows in list order. */
16
- export function chargeBody(ctx: SemanticsContext, c: Row): Row {
17
- const data = newest(ctx, 'refund').filter((r) => r.charge === c.id);
18
- return { ...c, refunds: { object: 'list', data, has_more: false, total_count: data.length, url: `/v1/charges/${String(c.id)}/refunds` } };
19
- }
20
-
21
- // A charge is written as the event Stripe sends for it (docs.stripe.com/api/events/types; Stripe has no
22
- // `charge.created`): charge.succeeded, "Occurs whenever a charge is successful", for one made or authorized
23
- // (capture=false: its status is succeeded, captured false), and charge.failed, "Occurs whenever a failed charge attempt
24
- // occurs", for a declined attempt. The twin makes no pending charge (charge.pending, "Occurs whenever a pending charge is
25
- // created"): its charges settle when made.
26
- /** The create's parameters as the charge keeps them: without `card`, the request's card details ("A token, like the ones
27
- * returned by Stripe.js", or a hash of the number, expiry and CVC). The Charge object has no `card` property (served
28
- * spec, charge); the card it was made with is its payment_method_details. Kept, it answered the card's full number and
29
- * CVC back on every read of the charge. */
30
- function withoutCard(params: Row): Row {
31
- const { card: _card, ...rest } = params;
32
- return rest;
33
- }
34
-
35
- /** A Charges-API charge a declining test card refuses: a 402 card_error naming the failed charge Stripe records for the
36
- * attempt (docs.stripe.com/declines). */
37
- async function declinedCharge(ctx: SemanticsContext, decline: { code: string; decline_code?: string; message: string }): Promise<Response> {
38
- const params = ctx.params;
39
- const failedId = ctx.mint('charge');
40
- const amount = Number(params.amount) || 0;
41
- await created(ctx, 'charge', { ...withoutCard(params), id: failedId }, {
42
- ...chargeDefaults(failedId, amount, false, ctx.occurredAt), status: 'failed', paid: false, captured: false, capture_before: null,
43
- failure_code: decline.code, failure_message: decline.message, balance_transaction: null,
44
- outcome: { type: 'issuer_declined', network_status: 'declined_by_network', reason: decline.decline_code ?? decline.code, risk_level: 'normal', seller_message: 'The bank did not return any further details with this decline.' },
45
- payment_method_details: paymentMethodDetails(ctx, params.payment_method ?? params.source ?? params.card) ?? null,
46
- }, { operation: 'charge.failed' });
47
- return send(ctx, cardError(decline, { charge: failedId }));
48
- }
49
-
50
- /** A charge's fraud report: "user_report … Assessments reported by you. If set, possible values of are `safe` and
51
- * `fraudulent`" (docs.stripe.com/api/charges/object, fraud_details). */
52
- function fraudReport(ctx: SemanticsContext, existing: Row, fd: Row): Row | Response {
53
- const report = String(fd.user_report);
54
- if (report !== 'safe' && report !== 'fraudulent') return fail(ctx, "Invalid fraud_details[user_report]: must be 'safe' or 'fraudulent'.", 400, 'parameter_invalid_string_enum');
55
- const prior = existing.fraud_details && typeof existing.fraud_details === 'object' ? (existing.fraud_details as Row) : {};
56
- return { user_report: report, stripe_report: prior.stripe_report ?? null };
57
- }
58
-
59
- const create: Semantics = async (ctx) => {
60
- const params = ctx.params;
61
- const bad = validateMoney(params);
62
- if (bad) return send(ctx, bad);
63
- // a declining test card answers a 402 card_error naming the failed charge Stripe records for the attempt
64
- const decline = declineFor(finder(ctx), params);
65
- if (decline) return declinedCharge(ctx, decline);
66
- // capture=false authorizes only: succeeded and paid, but not captured, with a capture deadline
67
- const captured = !(params.capture !== undefined && !asBool(params.capture));
68
- // the id comes first so the charge's own `refunds` list can carry its URL
69
- const id = typeof params.id === 'string' && params.id ? params.id : ctx.mint('charge');
70
- const amount = Number(params.amount) || 0;
71
- // a captured charge credits the balance; an authorization does when it is captured
72
- const card = String(params.source ?? params.payment_method ?? (params.card as Row | undefined)?.number ?? '');
73
- const bt = captured ? await settleCharge(ctx, id, amount, String(params.currency ?? 'usd'), card) : null;
74
- const details = paymentMethodDetails(ctx, params.payment_method ?? params.source ?? params.card);
75
- await created(ctx, 'charge', { ...withoutCard(params), id }, { ...chargeDefaults(id, amount, captured, ctx.occurredAt), balance_transaction: bt, payment_method_details: details ?? null }, { operation: 'charge.succeeded' });
76
- await afterCharge(ctx, id, { amount, currency: String(params.currency ?? 'usd'), application_fee_amount: params.application_fee_amount, destination: (params.transfer_data as Row | undefined)?.destination }, params.payment_method ?? params.source ?? params.card);
77
- return ctx.reply(chargeBody(ctx, ctx.get('charge', id)!));
78
- };
79
-
80
- // capture takes `amount` (the whole authorization by default; docs.stripe.com/api/charges/capture); the rest of a
81
- // partial capture is released with no Refund (captureAuthorization). `amount_to_capture` is the
82
- // PaymentIntent capture's parameter, which a charge's capture does not know.
83
- const capture: Semantics = async (ctx) => {
84
- const id = at(ctx, 'charge');
85
- const ch = ctx.get('charge', id);
86
- if (!ch) return chargeMissing(ctx, id);
87
- const refused = ctx.legal('charge', 'captured', 'PostChargesChargeCapture', ch.captured === true ? 'true' : 'false', undefined, id);
88
- if (refused) return ctx.refuse(refused);
89
- // "Capturing a charge will always succeed, unless the charge is already refunded, expired, captured, or an invalid
90
- // capture amount is specified" (docs.stripe.com/api/charges/capture): a released authorization is refunded
91
- if (ch.refunded === true) return fail(ctx, `Charge ${id} has already been refunded.`, 400, 'charge_already_refunded');
92
- // a canceled PaymentIntent's authorization is released: "After it's canceled, no additional charges are made by the
93
- // PaymentIntent and any operations on the PaymentIntent fail with an error" (docs.stripe.com/api/payment_intents/cancel).
94
- // Where the documentation stops and the twin decides: its charge's capture answers payment_intent_unexpected_state
95
- // ("The PaymentIntent's state was incompatible with the operation", docs.stripe.com/error-codes), in the twin's words.
96
- const intent = typeof ch.payment_intent === 'string' ? ctx.get('payment_intent', ch.payment_intent) : undefined;
97
- if (intent?.status === 'canceled') return fail(ctx, `Charge ${id} belongs to PaymentIntent ${String(intent.id)}, which is canceled; its authorization was released.`, 400, 'payment_intent_unexpected_state');
98
- const full = Number(ch.amount) || 0;
99
- const toCapture = ctx.params.amount !== undefined ? Math.min(full, Math.max(0, Math.trunc(Number(ctx.params.amount) || 0))) : full;
100
- return ctx.reply(chargeBody(ctx, await captureAuthorization(ctx, ch, toCapture, 'PostChargesChargeCapture')));
101
- };
102
-
103
- /** A capture=false charge refunded while uncaptured: its authorization is released by the refund, as it would be
104
- * "automatically refunded if uncaptured" (spec/openapi.json.gz, `capture_before`). The charge stays uncaptured and
105
- * becomes refunded in full, a Refund records the release, and no money moves: none was ever received. Written as
106
- * charge.refunded. Where the documentation stops and the twin decides: Stripe's basil change ("Partially capturing or
107
- * canceling payments no longer creates a Refund", docs.stripe.com/changelog/basil/2025-03-31/remove-refund-from-partial-
108
- * capture-and-payment-cancellation-flow) names partial capture and cancellation, not a refund asked for, so a refund
109
- * still makes one; its reason is null and it has no balance transaction. Answers the Refund. */
110
- export async function releaseAuthorization(ctx: SemanticsContext, ch: Row, operationId: string, given: Row = {}): Promise<Row> {
111
- const id = String(ch.id);
112
- const full = Number(ch.amount) || 0;
113
- if (ch.refunded !== true) ctx.legal('charge', 'refunded', operationId, 'false', 'true', id);
114
- const refund = await created(ctx, 'refund', { ...given, charge: id, amount: full - (Number(ch.amount_refunded) || 0), currency: String(ch.currency ?? 'usd') }, {
115
- status: 'succeeded', metadata: {}, reason: null, receipt_number: null,
116
- balance_transaction: null, source_transfer_reversal: null, transfer_reversal: null, ...refundDestination(ch, 'reversal'),
117
- ...(typeof ch.payment_intent === 'string' ? { payment_intent: ch.payment_intent } : {}),
118
- });
119
- await ctx.write('charge', id, { amount_refunded: full, refunded: true }, 'charge.refunded');
120
- return refund;
121
- }
122
-
123
- /** A PaymentIntent's authorization released by its cancel: "For PaymentIntents with a `status` of `requires_capture`, the
124
- * remaining `amount_capturable` is automatically refunded" (docs.stripe.com/api/payment_intents/cancel), and since basil
125
- * a cancellation makes no Refund: "`amount_captured` will be 0 instead of `nil` in payment cancellation flows",
126
- * "`amount_refunded` will no longer be updated by these actions", "`refunded` will no longer be `true` for payment
127
- * cancellation flows", and no charge.refunded is sent (docs.stripe.com/changelog/basil/2025-03-31/remove-refund-from-
128
- * partial-capture-and-payment-cancellation-flow). The charge stays uncaptured; nothing is written as an event. */
129
- export async function cancelAuthorization(ctx: SemanticsContext, ch: Row): Promise<Row> {
130
- return ctx.write('charge', String(ch.id), { amount_captured: 0 }, 'charge.authorization_released');
131
- }
132
-
133
- /** An authorized charge captured, by the charge's capture or its PaymentIntent's: what is captured credits the balance.
134
- * Written as charge.captured, "Occurs whenever a previously uncaptured charge is captured" (docs.stripe.com/api/events/types).
135
- * A partial capture releases the rest with no Refund and leaves amount_refunded and refunded as they were: "The following
136
- * flows no longer result in a `Refund` object created and linked to the payment: Partial capture", "`amount_refunded`
137
- * will no longer be updated by these actions", and "There will only be a single balance transaction for partial captures"
138
- * (docs.stripe.com/changelog/basil/2025-03-31/remove-refund-from-partial-capture-and-payment-cancellation-flow).
139
- * The caller has asked the machine whether it may capture. */
140
- export async function captureAuthorization(ctx: SemanticsContext, ch: Row, toCapture: number, _operationId: string): Promise<Row> {
141
- const id = String(ch.id);
142
- const bt = toCapture > 0 ? await settleCharge(ctx, id, toCapture, String(ch.currency ?? 'usd'), String(ch.source ?? ch.payment_method ?? '')) : null;
143
- return ctx.write('charge', id, { captured: true, amount_captured: toCapture, balance_transaction: bt }, 'charge.captured');
144
- }
145
-
146
- const listCharges: Semantics = async (ctx) => {
1
+ // Stripe's charges operations (docs/contributing/architecture.md, "What an author writes"): each handler over the
2
+ // handler contract's context, computing with the engine (../engine/).
3
+ import type { HandlerContext } from '@volter/world-core';
4
+ import { withoutCard } from '../engine/charges.ts';
5
+ import type { Row } from '../engine/common.ts';
6
+ import { asBool, chargeDefaults, declineFor, searchOver, validateMoney } from '../engine/stripe.ts';
7
+ import { afterCharge, at, captureAuthorization, chargeBody, chargeMissing, chargeRefund, created, declinedCharge, expanded, fail, finder, fraudReport, list, newest, path, paymentMethodDetails, refundCharge, send, settleCharge, where } from './shared.ts';
8
+
9
+ export async function GetCharges(ctx: HandlerContext): Promise<Response> {
147
10
  const items = where(ctx, newest(ctx, 'charge'), {
148
11
  customer: (c, v) => c.customer === v,
149
12
  payment_intent: (c, v) => c.payment_intent === v,
150
13
  });
151
14
  return list(ctx, 'charge', items.map((c) => chargeBody(ctx, c)));
152
- };
153
-
154
- const searchCharges: Semantics = async (ctx) => {
155
- const found = searchOver(newest(ctx, 'charge'), ctx.params, path(ctx));
156
- const body = found.body as { data?: Row[] };
157
- if (found.status === 200 && Array.isArray(body.data)) body.data = body.data.map((c) => chargeBody(ctx, c));
158
- return send(ctx, found);
159
- };
15
+ }
160
16
 
161
- const retrieve: Semantics = async (ctx) => {
17
+ export async function GetChargesCharge(ctx: HandlerContext): Promise<Response> {
162
18
  const c = ctx.get('charge', at(ctx, 'charge'));
163
19
  return c ? ctx.reply(expanded(ctx, 'charge', chargeBody(ctx, c))) : chargeMissing(ctx, at(ctx, 'charge'));
164
- };
165
-
166
- // fraud_details[user_report] marks a charge safe or fraudulent; Stripe keeps its own stripe_report
167
- const update: Semantics = async (ctx) => {
168
- const id = at(ctx, 'charge');
169
- const existing = ctx.get('charge', id);
170
- if (!existing) return chargeMissing(ctx, id);
171
- const fields: Row = { ...ctx.params };
172
- const fd = ctx.params.fraud_details;
173
- const fraud = fd && typeof fd === 'object' && 'user_report' in (fd as Row) ? fraudReport(ctx, existing, fd as Row) : undefined;
174
- if (fraud instanceof Response) return fraud;
175
- if (fraud) fields.fraud_details = fraud;
176
- return ctx.reply(chargeBody(ctx, await ctx.write('charge', id, fields, 'charge.update')));
177
- };
178
-
179
- // ── the charge's own refunds: listed, created and read through it; another charge's refund is not found ──
180
-
181
- const refunds: Semantics = async (ctx) => {
182
- const id = at(ctx, 'charge');
183
- if (!ctx.get('charge', id)) return chargeMissing(ctx, id);
184
- return list(ctx, 'refund', newest(ctx, 'refund').filter((r) => r.charge === id));
185
- };
186
-
187
- const createRefund: Semantics = async (ctx) => {
188
- const ch = ctx.get('charge', at(ctx, 'charge'));
189
- if (!ch) return chargeMissing(ctx, at(ctx, 'charge'));
190
- return refundCharge(ctx, ch, ctx.params);
191
- };
192
-
193
- const chargeRefund = (ctx: SemanticsContext): Row | Response => {
194
- if (!ctx.get('charge', at(ctx, 'charge'))) return chargeMissing(ctx, at(ctx, 'charge'));
195
- const r = ctx.get('refund', at(ctx, 'refund'));
196
- return r && r.charge === at(ctx, 'charge') ? r : fail(ctx, `No such refund: '${at(ctx, 'refund')}'`, 404, 'resource_missing');
197
- };
198
-
199
- const refund: Semantics = async (ctx) => {
200
- const r = chargeRefund(ctx);
201
- return r instanceof Response ? r : ctx.reply(r);
202
- };
203
-
204
- const updateRefund: Semantics = async (ctx) => {
205
- const r = chargeRefund(ctx);
206
- return r instanceof Response ? r : ctx.reply(await ctx.write('refund', at(ctx, 'refund'), ctx.params, 'refund.update'));
207
- };
20
+ }
208
21
 
209
- export const charges: Record<string, Semantics> = {
210
- PostCharges: create,
211
- PostChargesChargeCapture: capture,
212
- GetCharges: listCharges,
213
- GetChargesSearch: searchCharges,
214
- GetChargesCharge: retrieve,
215
- PostChargesCharge: update,
216
- GetChargesChargeRefunds: refunds,
217
- PostChargesChargeRefunds: createRefund,
218
- GetChargesChargeRefundsRefund: refund,
219
- PostChargesChargeRefundsRefund: updateRefund,
220
- };