@volter/twin-stripe 2.0.38 → 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,281 +0,0 @@
1
- // A subscription's invoices over time: the first one Checkout pays, and each renewal. Time's moves are made
2
- // as the twin's trial end already made them: caught up to the customer's clock (the World's, or its test
3
- // clock) whenever the twin is asked anything (../stripe-server.ts), each checked against the machines in
4
- // ../manifest.ts.
5
- //
6
- // - Checkout's subscription session pays the first invoice with the card the customer entered, which becomes the
7
- // subscription's default payment method (docs.stripe.com/payments/checkout/how-checkout-works); nothing is due
8
- // on a trial's.
9
- // - At each period's end Stripe drafts a `subscription_cycle` invoice for the next period and advances the
10
- // period; a trial's end is the first such renewal, and the subscription is active from then
11
- // (docs.stripe.com/billing/subscriptions/overview#how-payments-work-subscriptions,
12
- // docs.stripe.com/billing/subscriptions/trials).
13
- // - About an hour after, Stripe finalizes the draft and charges the subscription's default payment method,
14
- // else the customer's (docs.stripe.com/invoicing/integration/workflow-transitions#finalized,
15
- // docs.stripe.com/api/subscriptions/object#subscription_object-default_payment_method).
16
- // - A declined renewal leaves the invoice open with its attempt counted and the subscription past_due
17
- // (docs.stripe.com/billing/subscriptions/overview#payment-status); paying the invoice later, through the API
18
- // (docs.stripe.com/api/invoices/pay) or on the customer portal (docs.stripe.com/customer-management), makes it
19
- // active again.
20
- //
21
- // Where the documentation stops and the twin decides: Stripe retries a failed renewal on its Smart Retries
22
- // schedule and may then cancel or mark the subscription unpaid; the twin makes no retry (next_payment_attempt
23
- // is null) and leaves it past_due until the invoice is paid. A paused subscription (pause_collection) is not renewed.
24
- // - One set to cancel at its period's end is canceled when the period ends, with no renewal
25
- // (docs.stripe.com/billing/subscriptions/cancel#cancel-at-end-of-cycle).
26
- import { runAsVendorMove } from '@volter/world-core';
27
- import { addBillingInterval, applyCouponDiscount, declineFor, mintClientSecret, priceAmount, resolveSubscriptionBillingInterval } from "../stripe-twin.js";
28
- import { finalizedFields } from "./invoices.js";
29
- import { mintCharge } from "./payment-intents.js";
30
- import { at_, created, finder } from "./shared.js";
31
- const SUB = 'subscription';
32
- const INV = 'invoice';
33
- const HOUR = 3600;
34
- /** The statuses a subscription renews in. */
35
- const RENEWING = ['trialing', 'active', 'past_due'];
36
- /** A customer's now: its test clock's frozen time when it is on one (docs.stripe.com/billing/testing/test-clocks), the
37
- * World's otherwise. */
38
- export function clockNow(ctx, customer) {
39
- const clock = typeof customer === 'string' ? ctx.get('customer', customer)?.test_clock : undefined;
40
- const frozen = typeof clock === 'string' ? ctx.get('test_helpers.test_clock', clock)?.frozen_time : undefined;
41
- return frozen !== undefined ? Number(frozen) : Number(ctx.now());
42
- }
43
- /** What a subscription's invoices charge: its own default payment method, else its customer's. */
44
- export function payerOf(ctx, sub) {
45
- return typeof sub.default_payment_method === 'string' && sub.default_payment_method ? sub.default_payment_method : customerDefault(ctx, sub);
46
- }
47
- /** The customer's default for invoices, charged when the subscription names none of its own. */
48
- function customerDefault(ctx, sub) {
49
- const customer = typeof sub.customer === 'string' ? ctx.get('customer', sub.customer) : undefined;
50
- const settings = customer?.invoice_settings;
51
- return typeof settings?.default_payment_method === 'string' && settings.default_payment_method ? settings.default_payment_method : undefined;
52
- }
53
- const itemsOf = (sub) => (sub.items?.data) ?? [];
54
- /** An item's quantity as it bills: 1 when none is set, and 0 when 0 is (a quantity of 0 bills nothing). */
55
- export function itemQuantity(it) {
56
- return it.quantity === undefined || it.quantity === null ? 1 : Math.max(0, Math.trunc(Number(it.quantity) || 0));
57
- }
58
- /** The subscription's discounts with a `once` coupon's spent: "When a subscription uses a coupon with `duration=once`, the
59
- * coupon is considered used after the invoice finalizes and is removed from the subscription's `discounts` array"
60
- * (docs.stripe.com/billing/subscriptions/coupons#coupon-duration). */
61
- export function unspentDiscounts(discounts) {
62
- return (discounts ?? []).filter((d) => !(d && typeof d === 'object' && d.coupon?.duration === 'once'));
63
- }
64
- /** The coupon ids an invoice's discounts name. */
65
- const couponsOf = (discounts) => new Set((discounts ?? []).map((d) => {
66
- const c = d && typeof d === 'object' ? d.coupon : undefined;
67
- return typeof c === 'string' ? c : c && typeof c === 'object' ? String(c.id ?? '') : '';
68
- }).filter(Boolean));
69
- /** A subscription whose invoice has just been finalized: the `once` coupon that invoice took is spent, and a once coupon
70
- * it did not take (added after it was drafted) stays for the next (unspentDiscounts). */
71
- export async function spendOnceCoupon(ctx, invoice) {
72
- const subId = typeof invoice.subscription === 'string' ? invoice.subscription : undefined;
73
- const sub = subId ? ctx.get(SUB, subId) : undefined;
74
- if (!sub || !subId)
75
- return;
76
- const all = sub.discounts ?? [];
77
- const kept = keptAfter(all, invoice);
78
- if (kept.length !== all.length)
79
- await ctx.write(SUB, subId, { discounts: kept }, 'subscription.discount_spent');
80
- }
81
- /** A subscription's discounts after `invoice` finalizes: less the `once` coupons it took. */
82
- export function keptAfter(discounts, invoice) {
83
- const taken = couponsOf(invoice.discounts);
84
- return discounts.filter((d) => !(unspentDiscounts([d]).length === 0 && [...couponsOf([d])].some((c) => taken.has(c))));
85
- }
86
- /** A draft invoice for one period of a subscription, its lines the subscription's items and any one-time lines `once`
87
- * gives it (a Checkout session's one-time prices, "on the initial invoice only", docs.stripe.com/api/checkout/sessions/
88
- * create#create_checkout_session-line_items), under the subscription's discount. Answers the invoice id. */
89
- export async function draftSubscriptionInvoice(ctx, sub, o) {
90
- const id = o.id ?? ctx.mint(INV);
91
- const currency = String(sub.currency ?? 'usd');
92
- const lines = itemsOf(sub).map((it, i) => {
93
- const price = it.price && typeof it.price === 'object' ? it.price : ctx.get('price', String(it.price ?? ''));
94
- const quantity = itemQuantity(it);
95
- return {
96
- id: `il_twin_${id}_${i + 1}`, object: 'line_item', type: 'subscription',
97
- // a trial's first invoice bills nothing for the trial period (docs.stripe.com/billing/subscriptions/trials)
98
- amount: o.trial ? 0 : priceAmount(price, quantity), currency, quantity, proration: false,
99
- price: price ?? null, subscription: sub.id, subscription_item: it.id ?? null, invoice_item: null,
100
- period: { start: o.start, end: o.end }, description: o.trial ? `Trial period for ${String(ctx.get('product', String(price?.product ?? ''))?.name ?? 'the plan')}` : null,
101
- };
102
- });
103
- if (o.once?.length)
104
- lines.push(...oneTimeLines(id, sub, o.once, lines.length, o.start, currency));
105
- const subtotal = lines.reduce((s, l) => s + l.amount, 0);
106
- // a discount the subscription still carries applies; a `once` coupon is removed once an invoice finalizes
107
- // (spendOnceCoupon), so it discounts one invoice (docs.stripe.com/billing/subscriptions/coupons#coupon-duration)
108
- const discount = (sub.discounts ?? [])[0];
109
- const coupon = discount && typeof discount === 'object' ? discount.coupon : undefined;
110
- const off = coupon ? applyCouponDiscount(subtotal, coupon) : 0;
111
- const total = Math.max(0, subtotal - off);
112
- await created(ctx, INV, { id, customer: sub.customer, subscription: sub.id }, {
113
- created: o.start, status: 'draft', livemode: false, currency, collection_method: 'charge_automatically',
114
- billing_reason: o.reason, auto_advance: true, attempt_count: 0, attempted: false, next_payment_attempt: null,
115
- amount_due: total, amount_paid: 0, amount_remaining: total, amount_overpaid: 0, amount_paid_off_stripe: 0, amount_shipping: 0,
116
- subtotal, total, starting_balance: 0, post_payment_credit_notes_amount: 0, pre_payment_credit_notes_amount: 0,
117
- // "The invoice that consumed the coupon still shows the applied discount" (docs.stripe.com/billing/subscriptions/coupons)
118
- period_start: o.start, period_end: o.end, default_tax_rates: [], discounts: coupon && discount ? [discount] : [],
119
- lines: { object: 'list', data: lines, has_more: false, total_count: lines.length, url: `/v1/invoices/${id}/lines` },
120
- automatic_tax: { enabled: false, liability: null, status: null },
121
- status_transitions: { finalized_at: null, marked_uncollectible_at: null, paid_at: null, voided_at: null },
122
- issuer: { type: 'self' }, payment_settings: { default_mandate: null, payment_method_options: null, payment_method_types: null },
123
- payment_intent: null, charge: null,
124
- });
125
- return id;
126
- }
127
- /** A Checkout session's one-time line items as lines of its subscription's first invoice, numbered after its `after` lines. */
128
- function oneTimeLines(invoiceId, sub, items, after, at, currency) {
129
- return items.map((it, i) => {
130
- const price = it.price && typeof it.price === 'object' ? it.price : null;
131
- const quantity = itemQuantity(it);
132
- return {
133
- id: `il_twin_${invoiceId}_${after + i + 1}`, object: 'line_item', type: 'subscription',
134
- amount: priceAmount(price ?? undefined, quantity), currency, quantity, proration: false,
135
- price, subscription: sub.id, subscription_item: null, invoice_item: null,
136
- period: { start: at, end: at }, description: typeof it.description === 'string' ? it.description : null,
137
- };
138
- });
139
- }
140
- /** Finalize a subscription's draft invoice at `at` and charge what its subscription pays with. The move is time's (a
141
- * renewal), the customer's (the Checkout page they paid on) or the API's (an update that ends a trial, which names the
142
- * payer, may ask for no attempt, and moves the subscription itself: semantics/subscriptions.ts applyTrialEnd). Answers
143
- * whether it was paid. */
144
- export async function collectSubscriptionInvoice(ctx, invoiceId, at, actor, opts = {}) {
145
- const inv = ctx.get(INV, invoiceId);
146
- const sub = inv && typeof inv.subscription === 'string' ? ctx.get(SUB, inv.subscription) : undefined;
147
- if (!inv || !sub || inv.status !== 'draft')
148
- return false;
149
- const total = Number(inv.total) || 0;
150
- const numbered = { ...finalizedFields(ctx, inv, at), status_transitions: { ...inv.status_transitions, finalized_at: at } };
151
- const op = ctx.call.operation.id;
152
- // nothing due (a trial's first invoice) is paid as it is finalized; finalizing spends a `once` coupon
153
- if (total <= 0) {
154
- if (ctx.legal(INV, 'status', op, 'draft', 'paid', invoiceId, actor))
155
- return false;
156
- await spendOnceCoupon(ctx, inv);
157
- await ctx.write(INV, invoiceId, { ...numbered, status: 'paid', paid: true, auto_advance: false, status_transitions: { ...numbered.status_transitions, paid_at: at } }, 'invoice.paid');
158
- return true;
159
- }
160
- const payer = actor === 'api' ? opts.payer : payerOf(ctx, sub);
161
- // default_incomplete finalizes the invoice without attempting payment (docs.stripe.com/api/subscriptions/update#update_subscription-payment_behavior)
162
- const attempt = opts.attempt !== false;
163
- const decline = payer && attempt ? declineFor(finder(ctx), { payment_method: payer }) : undefined;
164
- const pays = attempt && !!payer && !decline;
165
- if (ctx.legal(INV, 'status', op, 'draft', pays ? 'paid' : 'open', invoiceId, actor))
166
- return false;
167
- await spendOnceCoupon(ctx, inv);
168
- const piId = ctx.mint('payment_intent');
169
- const currency = String(inv.currency ?? 'usd');
170
- const chargeId = pays ? await mintCharge(ctx, piId, { currency, customer: inv.customer, payment_method: payer, invoice: invoiceId }, total) : null;
171
- await created(ctx, 'payment_intent', { id: piId, amount: total, currency, customer: inv.customer, invoice: invoiceId, payment_method: pays ? payer : null }, {
172
- status: pays ? 'succeeded' : 'requires_payment_method', client_secret: mintClientSecret(piId), livemode: false,
173
- capture_method: 'automatic', amount_capturable: 0, amount_received: pays ? total : 0, next_action: null, latest_charge: chargeId,
174
- last_payment_error: decline ? { type: 'card_error', code: decline.code, decline_code: decline.decline_code ?? null, message: decline.message, payment_method: { id: payer } } : null,
175
- automatic_payment_methods: null, payment_method_types: ['card'], payment_method_options: {},
176
- });
177
- await ctx.write(INV, invoiceId, {
178
- ...numbered, status: pays ? 'paid' : 'open', paid: pays, attempt_count: attempt ? 1 : 0, attempted: attempt, payment_intent: piId, charge: chargeId,
179
- amount_paid: pays ? total : 0, amount_remaining: pays ? 0 : total, auto_advance: attempt && !pays, next_payment_attempt: null,
180
- status_transitions: { ...numbered.status_transitions, paid_at: pays ? at : null },
181
- }, pays ? 'invoice.paid' : attempt ? 'invoice.payment_failed' : 'invoice.finalized');
182
- if (actor !== 'api' && !pays && sub.status !== 'past_due' && !ctx.legal(SUB, 'status', op, sub.status, 'past_due', String(sub.id), 'time')) {
183
- await ctx.write(SUB, String(sub.id), { status: 'past_due' }, 'customer.subscription.updated');
184
- }
185
- return pays;
186
- }
187
- /** Pay a subscription's open invoice with `paymentMethod` (the customer on the portal, `external`): the charge on the
188
- * invoice's PaymentIntent, the invoice paid, a past_due subscription active. Answers the decline, if the card is refused. */
189
- export async function payOpenInvoice(ctx, invoiceId, paymentMethod) {
190
- const inv = ctx.get(INV, invoiceId);
191
- if (!inv || inv.status !== 'open')
192
- return { code: 'invoice_not_open', message: 'This invoice is no longer open.' };
193
- const decline = declineFor(finder(ctx), { payment_method: paymentMethod });
194
- if (decline)
195
- return decline;
196
- const op = ctx.call.operation.id;
197
- const refused = ctx.legal(INV, 'status', op, 'open', 'paid', invoiceId, 'external');
198
- if (refused)
199
- return { code: refused.code ?? 'invoice_not_open', message: refused.message };
200
- const total = Number(inv.amount_remaining ?? inv.total) || 0;
201
- const now = Number(ctx.now());
202
- const piId = typeof inv.payment_intent === 'string' ? inv.payment_intent : undefined;
203
- let chargeId = null;
204
- const pi = piId ? ctx.get('payment_intent', piId) : undefined;
205
- if (piId && pi && !ctx.legal('payment_intent', 'status', op, pi.status, 'succeeded', piId, 'external')) {
206
- chargeId = await mintCharge(ctx, piId, { ...pi, payment_method: paymentMethod, invoice: invoiceId }, total);
207
- await ctx.write('payment_intent', piId, { status: 'succeeded', payment_method: paymentMethod, amount_received: total, last_payment_error: null, latest_charge: chargeId }, 'payment_intent.succeeded');
208
- }
209
- await ctx.write(INV, invoiceId, {
210
- status: 'paid', paid: true, amount_paid: total, amount_remaining: 0, charge: chargeId, auto_advance: false,
211
- attempt_count: (Number(inv.attempt_count) || 0) + 1, attempted: true,
212
- status_transitions: { ...inv.status_transitions, paid_at: now },
213
- }, 'invoice.paid');
214
- const sub = typeof inv.subscription === 'string' ? ctx.get(SUB, inv.subscription) : undefined;
215
- if (sub && sub.status === 'past_due' && !ctx.legal(SUB, 'status', op, 'past_due', 'active', String(sub.id), 'external')) {
216
- await ctx.write(SUB, String(sub.id), { status: 'active' }, 'customer.subscription.updated');
217
- }
218
- return undefined;
219
- }
220
- /** Time's moves on subscriptions, caught up to each customer's clock in the order they fell due, each made at the
221
- * moment it was due: a period that ended renews (a trial's end among them) or, set to cancel, cancels; a renewal
222
- * drafted an hour or more ago is finalized and charged. */
223
- export async function advanceBilling(ctx, only) {
224
- // the billing clock is the vendor's own move, wherever a handler reaches it: never the request's caller's
225
- return runAsVendorMove(() => advanceBillingDue(ctx, only));
226
- }
227
- async function advanceBillingDue(ctx, only) {
228
- const at = at_(ctx);
229
- for (let guard = 0; guard < 10_000 && (await billingStep(ctx, at, only)); guard++)
230
- ;
231
- }
232
- /** The earliest move that has come due, made at its moment; false when none has. */
233
- async function billingStep(ctx, at, only) {
234
- // the earliest move that has come due, of any subscription
235
- let next;
236
- for (const sub of ctx.rows(SUB)) {
237
- if (only && !only(sub))
238
- continue;
239
- if (!RENEWING.includes(String(sub.status)) || typeof sub.current_period_end !== 'number' || sub.pause_collection)
240
- continue;
241
- if (sub.current_period_end <= clockNow(ctx, sub.customer) && (!next || sub.current_period_end < next.t))
242
- next = { t: sub.current_period_end, kind: 'period', id: String(sub.id) };
243
- }
244
- for (const inv of ctx.rows(INV)) {
245
- if (inv.status !== 'draft' || inv.billing_reason !== 'subscription_cycle' || inv.auto_advance !== true)
246
- continue;
247
- const sub = typeof inv.subscription === 'string' ? ctx.get(SUB, inv.subscription) : undefined;
248
- if (!sub || (only && !only(sub)))
249
- continue;
250
- const t = Number(inv.created) + HOUR;
251
- if (t <= clockNow(ctx, sub.customer) && (!next || t < next.t))
252
- next = { t, kind: 'collect', id: String(inv.id) };
253
- }
254
- if (!next)
255
- return false;
256
- const c = await at(next.t);
257
- if (next.kind === 'collect') {
258
- await collectSubscriptionInvoice(c, next.id, next.t, 'time');
259
- return true;
260
- }
261
- const id = next.id;
262
- const sub = c.get(SUB, id);
263
- const op = c.call.operation.id;
264
- // one set to cancel at its period's end is canceled then, with no renewal
265
- // (docs.stripe.com/billing/subscriptions/cancel#cancel-at-end-of-cycle)
266
- if (sub.cancel_at_period_end === true) {
267
- if (c.legal(SUB, 'status', op, sub.status, 'canceled', id, 'time'))
268
- return false;
269
- await c.write(SUB, id, { status: 'canceled', ended_at: next.t, canceled_at: sub.canceled_at ?? next.t }, 'customer.subscription.deleted');
270
- return true;
271
- }
272
- const start = next.t;
273
- const { interval, interval_count } = resolveSubscriptionBillingInterval(itemsOf(sub), finder(c));
274
- const end = addBillingInterval(start, interval, interval_count);
275
- const trialEnds = sub.status === 'trialing';
276
- if (trialEnds && c.legal(SUB, 'status', op, 'trialing', 'active', id, 'time'))
277
- return false;
278
- const invoiceId = await draftSubscriptionInvoice(c, sub, { start, end, reason: 'subscription_cycle' });
279
- await c.write(SUB, id, { current_period_start: start, current_period_end: end, latest_invoice: invoiceId, ...(trialEnds ? { status: 'active' } : {}) }, 'customer.subscription.updated');
280
- return true;
281
- }
@@ -1,2 +0,0 @@
1
- import type { Semantics } from '@volter/world-core';
2
- export declare const setupIntents: Record<string, Semantics>;
@@ -1,2 +0,0 @@
1
- import type { Semantics } from '@volter/world-core';
2
- export declare const subscriptionSchedules: Record<string, Semantics>;
@@ -1,119 +0,0 @@
1
- import { addBillingInterval, buildSubscriptionItemsList } from "../stripe-twin.js";
2
- import { at, created, fail, finder } from "./shared.js";
3
- import { storeItems } from "./subscriptions.js";
4
- const SS = 'subscription_schedule';
5
- const scheduleMissing = (ctx, id) => fail(ctx, `No such subscription_schedule: '${id}'`, 404, 'resource_missing');
6
- /** A schedule's phases as Stripe answers them (the served spec's subscription_schedule_phase_configuration): each
7
- * starts where the last ended (the first at the schedule's start_date, "now" or a timestamp), and ends at its
8
- * end_date or after its duration ("duration: interval, interval_count", the served spec's phases[] parameter) on the
9
- * calendar; its currency is its first price's, each item carries its price, quantity and (empty) discounts. Where the
10
- * documentation stops and the twin decides: a phase with neither lasts one interval of its first price. */
11
- function phasesOf(ctx, given, start) {
12
- let cursor = start;
13
- return given.map((p) => {
14
- const items = (Array.isArray(p.items) ? p.items : []).map((it) => ({ price: it.price ?? null, quantity: Math.max(1, Math.trunc(Number(it.quantity) || 1)), discounts: [], metadata: {}, tax_rates: [], billing_thresholds: null }));
15
- const price = typeof items[0]?.price === 'string' ? ctx.get('price', items[0].price) : undefined;
16
- const recurring = price?.recurring ?? {};
17
- const d = p.duration && typeof p.duration === 'object' ? p.duration : undefined;
18
- const startDate = cursor;
19
- const end = p.end_date !== undefined && p.end_date !== 'now' ? Number(p.end_date)
20
- : d ? addBillingInterval(startDate, String(d.interval), Math.max(1, Number(d.interval_count) || 1))
21
- : addBillingInterval(startDate, String(recurring.interval ?? 'month'), Math.max(1, Number(recurring.interval_count) || 1));
22
- cursor = end;
23
- return {
24
- add_invoice_items: [], application_fee_percent: null, automatic_tax: { enabled: false, liability: null, disabled_reason: null }, billing_cycle_anchor: null,
25
- billing_thresholds: null, collection_method: null, currency: String(price?.currency ?? 'usd'), default_payment_method: null, default_tax_rates: [],
26
- description: null, discounts: [], end_date: end, invoice_settings: null, items, metadata: p.metadata && typeof p.metadata === 'object' ? p.metadata : {},
27
- on_behalf_of: null, proration_behavior: typeof p.proration_behavior === 'string' ? p.proration_behavior : 'create_prorations', start_date: startDate,
28
- transfer_data: null, trial_end: null,
29
- };
30
- });
31
- }
32
- // a schedule starts from a customer or from an existing subscription
33
- const create = async (ctx) => {
34
- const params = ctx.params;
35
- const customer = typeof params.customer === 'string' ? params.customer : '';
36
- const fromSub = typeof params.from_subscription === 'string' ? params.from_subscription : '';
37
- if (!customer && !fromSub)
38
- return fail(ctx, 'Missing required param: customer (or from_subscription).', 400, 'parameter_missing');
39
- if (customer && !ctx.get('customer', customer))
40
- return fail(ctx, `No such customer: '${customer}'`, 404, 'resource_missing');
41
- if (fromSub && !ctx.get('subscription', fromSub))
42
- return fail(ctx, `No such subscription: '${fromSub}'`, 404, 'resource_missing');
43
- // start_date is an instruction ("now" or when), not a field of the schedule
44
- const start = params.start_date !== undefined && params.start_date !== 'now' ? Number(params.start_date) : Number(ctx.now());
45
- const phases = phasesOf(ctx, Array.isArray(params.phases) ? params.phases : [], start);
46
- const { phases: _p, start_date: _s, default_settings: givenDefaults, ...rest } = params;
47
- const defaults = givenDefaults && typeof givenDefaults === 'object' ? givenDefaults : {};
48
- const schedId = ctx.mint(SS);
49
- // a schedule for a customer whose first phase starts now starts its subscription at once, on that phase's items
50
- // (docs.stripe.com/billing/subscriptions/subscription-schedules#managing)
51
- let subscription = fromSub || null;
52
- if (!fromSub && phases.length) {
53
- const now = Number(ctx.now());
54
- const subId = ctx.mint('subscription');
55
- const items = buildSubscriptionItemsList(phases[0].items, subId, now, finder(ctx));
56
- await created(ctx, 'subscription', { customer, id: subId }, {
57
- status: 'active', livemode: false, currency: 'usd', collection_method: String(params.default_settings?.collection_method ?? 'charge_automatically'),
58
- cancel_at_period_end: false, start_date: now, billing_cycle_anchor: now, metadata: {}, discounts: [], billing_schedules: [],
59
- trial_start: null, trial_end: null, current_period_start: now, current_period_end: phases[0].end_date, items, schedule: schedId,
60
- automatic_tax: { enabled: false, liability: null }, billing_mode: { type: 'classic' }, invoice_settings: { issuer: { type: 'self' } },
61
- });
62
- await storeItems(ctx, subId, items.data ?? []);
63
- subscription = subId;
64
- }
65
- return ctx.reply(await created(ctx, SS, { ...rest, id: schedId }, {
66
- status: 'active', livemode: false, phases, current_phase: phases.length ? { start_date: phases[0].start_date, end_date: phases[0].end_date } : null,
67
- subscription, released_subscription: null, released_at: null,
68
- canceled_at: null, completed_at: null, end_behavior: params.end_behavior ?? 'release',
69
- renewal_interval: null, metadata: {}, billing_mode: { type: 'classic' },
70
- // "billing_cycle_anchor: Possible values are phase_start or automatic" and invoice_settings are required (the
71
- // served spec's default settings); the rest answer what the request set, else null
72
- default_settings: {
73
- application_fee_percent: defaults.application_fee_percent ?? null, automatic_tax: { enabled: false, liability: null, disabled_reason: null },
74
- billing_cycle_anchor: typeof defaults.billing_cycle_anchor === 'string' ? defaults.billing_cycle_anchor : 'automatic', billing_thresholds: null,
75
- collection_method: typeof defaults.collection_method === 'string' ? defaults.collection_method : 'charge_automatically', default_payment_method: defaults.default_payment_method ?? null,
76
- description: defaults.description ?? null, invoice_settings: { account_tax_ids: null, days_until_due: null, issuer: { type: 'self' } }, on_behalf_of: null, transfer_data: null,
77
- },
78
- // a schedule made from a subscription is its customer's
79
- customer: customer || String(ctx.get('subscription', fromSub)?.customer ?? ''),
80
- }));
81
- };
82
- function end(kind) {
83
- return async (ctx) => {
84
- const id = at(ctx, 'schedule');
85
- const sched = ctx.get(SS, id);
86
- if (!sched)
87
- return scheduleMissing(ctx, id);
88
- const refused = ctx.legal(SS, 'status', kind === 'cancel' ? 'PostSubscriptionSchedulesScheduleCancel' : 'PostSubscriptionSchedulesScheduleRelease', sched.status, undefined, id);
89
- if (refused)
90
- return ctx.refuse(refused);
91
- const now = ctx.now();
92
- const subId = typeof sched.subscription === 'string' ? sched.subscription : undefined;
93
- const sub = subId ? ctx.get('subscription', subId) : undefined;
94
- // "Cancels a subscription schedule and its associated subscription immediately (if the subscription schedule has an
95
- // active subscription)" (docs.stripe.com/api/subscription_schedules/cancel); releasing "will remove its subscription
96
- // property and set the subscription's ID to the released_subscription property", leaving the subscription in place
97
- // (docs.stripe.com/api/subscription_schedules/release)
98
- if (kind === 'cancel' && subId && sub && sub.status !== 'canceled') {
99
- ctx.legal('subscription', 'status', 'PostSubscriptionSchedulesScheduleCancel', String(sub.status), 'canceled', subId);
100
- await ctx.write('subscription', subId, { status: 'canceled', canceled_at: now, ended_at: now }, 'subscription.cancel');
101
- }
102
- if (kind === 'release' && subId && sub)
103
- await ctx.write('subscription', subId, { schedule: null }, 'subscription.update');
104
- const fields = kind === 'cancel'
105
- ? { status: 'canceled', canceled_at: now, current_phase: null }
106
- : { status: 'released', released_at: now, released_subscription: subId ?? null, subscription: null, current_phase: null };
107
- return ctx.reply(await ctx.write(SS, id, fields, `subscription_schedule.${kind}`));
108
- };
109
- }
110
- const retrieve = async (ctx) => {
111
- const s = ctx.get(SS, at(ctx, 'schedule'));
112
- return s ? ctx.reply(s) : scheduleMissing(ctx, at(ctx, 'schedule'));
113
- };
114
- export const subscriptionSchedules = {
115
- PostSubscriptionSchedules: create,
116
- PostSubscriptionSchedulesScheduleCancel: end('cancel'),
117
- PostSubscriptionSchedulesScheduleRelease: end('release'),
118
- GetSubscriptionSchedulesSchedule: retrieve,
119
- };
@@ -1,2 +0,0 @@
1
- import type { Semantics } from '@volter/world-core';
2
- export declare const tax: Record<string, Semantics>;
@@ -1,197 +0,0 @@
1
- import { asBool, lineItemEntries, paginate } from "../stripe-twin.js";
2
- import { at, created, fail, list, newest, path, where } from "./shared.js";
3
- const TWIN_TAX_RATE_PCT = 10;
4
- const createRate = async (ctx) => {
5
- const params = ctx.params;
6
- if (params.display_name === undefined || params.display_name === '')
7
- return fail(ctx, 'Missing required param: display_name.', 400, 'parameter_missing');
8
- if (params.percentage === undefined)
9
- return fail(ctx, 'Missing required param: percentage.', 400, 'parameter_missing');
10
- if (params.inclusive === undefined)
11
- return fail(ctx, 'Missing required param: inclusive.', 400, 'parameter_missing');
12
- return ctx.reply(await created(ctx, 'tax_rate', { ...params, inclusive: asBool(params.inclusive), percentage: Number(params.percentage) }, {
13
- active: true, livemode: false, metadata: {},
14
- country: null, state: null, jurisdiction: typeof params.jurisdiction === 'string' ? params.jurisdiction : null,
15
- jurisdiction_level: null, description: params.description ?? null, display_name: params.display_name,
16
- tax_type: null,
17
- }));
18
- };
19
- const listRates = async (ctx) => list(ctx, 'tax_rate', where(ctx, newest(ctx, 'tax_rate'), {
20
- active: (t, v) => asBool(t.active) === asBool(v),
21
- inclusive: (t, v) => asBool(t.inclusive) === asBool(v),
22
- }));
23
- // percentage and inclusive are fixed once created
24
- const updateRate = async (ctx) => {
25
- const id = at(ctx, 'tax_rate');
26
- if (!ctx.get('tax_rate', id))
27
- return ctx.notFound('tax_rate', id);
28
- const { percentage: _p, inclusive: _i, ...rest } = ctx.params;
29
- return ctx.reply(await ctx.write('tax_rate', id, { ...rest, ...('active' in rest ? { active: asBool(rest.active) } : {}) }, 'tax_rate.update'));
30
- };
31
- // ── settings: active once a head office is set; the answer has no id ──
32
- // the defaults' provider: "The tax calculation provider this account uses. Defaults to `stripe` when not using a
33
- // third-party provider" (the served spec's tax settings defaults); the head office's address answers each line, the
34
- // lines not given null (the served spec's address: each "(string, nullable)"; the settings page's example answers
35
- // line2 null)
36
- const ADDRESS_LINES = ['city', 'country', 'line1', 'line2', 'postal_code', 'state'];
37
- function settingsBody(stored) {
38
- const given = (stored?.head_office ?? null);
39
- const address = given && typeof given.address === 'object' && given.address ? given.address : undefined;
40
- const headOffice = given ? { ...given, ...(address ? { address: Object.fromEntries(ADDRESS_LINES.map((k) => [k, address[k] ?? null])) } : {}) } : null;
41
- const active = !!headOffice;
42
- return {
43
- object: 'tax.settings', livemode: false,
44
- defaults: { provider: 'stripe', ...(stored?.defaults ?? { tax_behavior: null, tax_code: null }) }, head_office: headOffice,
45
- status: active ? 'active' : 'pending',
46
- status_details: active ? { active: {} } : { pending: { missing_fields: ['head_office'] } },
47
- };
48
- }
49
- const getSettings = async (ctx) => ctx.reply(settingsBody(ctx.rows('tax.settings')[0]));
50
- const updateSettings = async (ctx) => {
51
- const existing = ctx.rows('tax.settings')[0];
52
- const cur = existing ?? {};
53
- const defaults = ctx.params.defaults && typeof ctx.params.defaults === 'object' ? ctx.params.defaults : {};
54
- const curDefaults = cur.defaults ?? {};
55
- const headOffice = ctx.params.head_office && typeof ctx.params.head_office === 'object' ? ctx.params.head_office : undefined;
56
- const fields = {
57
- defaults: {
58
- tax_behavior: typeof defaults.tax_behavior === 'string' ? defaults.tax_behavior : (curDefaults.tax_behavior ?? null),
59
- tax_code: typeof defaults.tax_code === 'string' ? defaults.tax_code : (curDefaults.tax_code ?? null),
60
- },
61
- head_office: headOffice ?? cur.head_office ?? null,
62
- livemode: false,
63
- };
64
- const body = await ctx.write('tax.settings', existing ? String(existing.id) : 'taxset_twin_1', fields, existing ? 'tax_settings.update' : 'tax_settings.create');
65
- return ctx.reply(settingsBody(body));
66
- };
67
- // ── calculations: each line's tax on top of its amount; no `created`, a tax_date instead ──
68
- const calcMissing = (ctx, id) => fail(ctx, `No such tax calculation: '${id}'`, 404, 'resource_missing');
69
- const calculate = async (ctx) => {
70
- const params = ctx.params;
71
- if (params.currency === undefined || params.currency === '')
72
- return fail(ctx, 'Missing required param: currency.', 400, 'parameter_missing');
73
- const entries = lineItemEntries(params);
74
- if (entries.length === 0)
75
- return fail(ctx, 'Missing required param: line_items.', 400, 'parameter_missing');
76
- const now = Number(ctx.now());
77
- const id = ctx.mint('tax.calculation');
78
- const items = entries.map((e, i) => {
79
- const amount = Math.max(0, Math.trunc(Number(e.amount) || 0));
80
- return {
81
- object: 'tax.calculation_line_item', id: `tax_li_${id}_${i + 1}`,
82
- amount, amount_tax: Math.round((amount * TWIN_TAX_RATE_PCT) / 100), reference: typeof e.reference === 'string' ? e.reference : null,
83
- tax_behavior: 'exclusive', tax_code: typeof e.tax_code === 'string' ? e.tax_code : 'txcd_99999999',
84
- quantity: e.quantity === undefined ? 1 : Math.max(1, Math.trunc(Number(e.quantity) || 1)), livemode: false,
85
- };
86
- });
87
- const amountSubtotal = items.reduce((s, it) => s + it.amount, 0);
88
- const taxExclusive = items.reduce((s, it) => s + it.amount_tax, 0);
89
- const cd = params.customer_details && typeof params.customer_details === 'object' ? params.customer_details : {};
90
- return ctx.reply(await created(ctx, 'tax.calculation', {
91
- id, currency: String(params.currency), amount_total: amountSubtotal + taxExclusive, tax_amount_exclusive: taxExclusive, tax_amount_inclusive: 0,
92
- customer: typeof params.customer === 'string' ? params.customer : null,
93
- customer_details: {
94
- address: cd.address ?? null, address_source: cd.address_source ?? 'shipping', ip_address: cd.ip_address ?? null,
95
- tax_ids: Array.isArray(cd.tax_ids) ? cd.tax_ids : [], taxability_override: cd.taxability_override ?? 'none',
96
- },
97
- line_items: { object: 'list', data: items, has_more: false, url: `/v1/tax/calculations/${id}/line_items` },
98
- shipping_cost: null, tax_date: now,
99
- tax_breakdown: taxExclusive > 0 ? [{
100
- amount: taxExclusive, inclusive: false, taxability_reason: 'standard_rated', taxable_amount: amountSubtotal,
101
- tax_rate_details: { country: null, percentage_decimal: String(TWIN_TAX_RATE_PCT), state: null, tax_type: 'sales_tax' },
102
- }] : [],
103
- expires_at: now + 90 * 24 * 3600, livemode: false,
104
- }, {}, { timeField: 'tax_date' }));
105
- };
106
- /** A page of the line items a stored object carries. */
107
- function linePage(ctx, holder) {
108
- const li = holder.line_items;
109
- const { page, hasMore } = paginate(Array.isArray(li?.data) ? li.data : [], ctx.params);
110
- return ctx.reply({ object: 'list', url: path(ctx), has_more: hasMore, data: page });
111
- }
112
- const calculationLines = async (ctx) => {
113
- const c = ctx.get('tax.calculation', at(ctx, 'calculation'));
114
- return c ? linePage(ctx, c) : calcMissing(ctx, at(ctx, 'calculation'));
115
- };
116
- // ── registrations ──
117
- const register = async (ctx) => {
118
- const params = ctx.params;
119
- if (params.country === undefined || params.country === '')
120
- return fail(ctx, 'Missing required param: country.', 400, 'parameter_missing');
121
- if (params.active_from === undefined)
122
- return fail(ctx, 'Missing required param: active_from.', 400, 'parameter_missing');
123
- const now = Number(ctx.now());
124
- const activeFrom = params.active_from === 'now' ? now : Number(params.active_from) || now;
125
- return ctx.reply(await created(ctx, 'tax.registration', { ...params, active_from: activeFrom }, {
126
- status: 'active', expires_at: null, livemode: false,
127
- country_options: params.country_options && typeof params.country_options === 'object' ? params.country_options : {},
128
- }));
129
- };
130
- // ── transactions: committing a calculation, or reversing a transaction with negated amounts ──
131
- const TX = 'tax.transaction';
132
- const txMissing = (ctx, id, status = 404) => fail(ctx, `No such tax transaction: '${id}'`, status, 'resource_missing');
133
- const txLine = (id, i, l, sign, reversal, type) => ({
134
- object: 'tax.transaction_line_item', id: `tax_li_${id}_${i + 1}`,
135
- amount: sign === 1 ? l.amount : -(Number(l.amount) || 0), amount_tax: sign === 1 ? l.amount_tax : -(Number(l.amount_tax) || 0),
136
- reference: l.reference ?? null, tax_behavior: l.tax_behavior ?? 'exclusive', tax_code: l.tax_code ?? 'txcd_99999999',
137
- quantity: l.quantity ?? 1, reversal, type, livemode: false, metadata: {},
138
- });
139
- const linesOf = (holder) => holder.line_items?.data ?? [];
140
- const fromCalculation = async (ctx) => {
141
- const calcId = typeof ctx.params.calculation === 'string' ? ctx.params.calculation : '';
142
- if (!calcId)
143
- return fail(ctx, 'Missing required param: calculation.', 400, 'parameter_missing');
144
- if (ctx.params.reference === undefined || ctx.params.reference === '')
145
- return fail(ctx, 'Missing required param: reference.', 400, 'parameter_missing');
146
- const calc = ctx.get('tax.calculation', calcId);
147
- if (!calc)
148
- return fail(ctx, `No such tax calculation: '${calcId}'`, 400, 'resource_missing');
149
- const id = ctx.mint(TX);
150
- const now = ctx.now();
151
- return ctx.reply(await created(ctx, TX, {
152
- id, _stripe_type: 'transaction', reference: ctx.params.reference, currency: calc.currency,
153
- customer: calc.customer ?? null, customer_details: calc.customer_details ?? {},
154
- tax_date: now, livemode: false, posted_at: now,
155
- line_items: { object: 'list', data: linesOf(calc).map((l, i) => txLine(id, i, l, 1, null, 'transaction')), has_more: false, url: `/v1/tax/transactions/${id}/line_items` },
156
- shipping_cost: calc.shipping_cost ?? null, reversal: null, calculation: calcId, metadata: {},
157
- }, {}));
158
- };
159
- const reversal = async (ctx) => {
160
- const original = typeof ctx.params.original_transaction === 'string' ? ctx.params.original_transaction : '';
161
- if (!original)
162
- return fail(ctx, 'Missing required param: original_transaction.', 400, 'parameter_missing');
163
- if (ctx.params.reference === undefined || ctx.params.reference === '')
164
- return fail(ctx, 'Missing required param: reference.', 400, 'parameter_missing');
165
- const mode = typeof ctx.params.mode === 'string' ? ctx.params.mode : '';
166
- if (mode !== 'full' && mode !== 'partial')
167
- return fail(ctx, 'Missing required param: mode (full or partial).', 400, 'parameter_missing');
168
- const orig = ctx.get(TX, original);
169
- if (!orig)
170
- return txMissing(ctx, original, 400);
171
- const id = ctx.mint(TX);
172
- const now = ctx.now();
173
- return ctx.reply(await created(ctx, TX, {
174
- id, _stripe_type: 'reversal', reference: ctx.params.reference, currency: orig.currency,
175
- customer: orig.customer ?? null, customer_details: orig.customer_details ?? {},
176
- tax_date: now, livemode: false, posted_at: now,
177
- line_items: { object: 'list', data: linesOf(orig).map((l, i) => txLine(id, i, l, -1, { original_line_item: l.id }, 'reversal')), has_more: false, url: `/v1/tax/transactions/${id}/line_items` },
178
- shipping_cost: null, reversal: { original_transaction: original, mode }, metadata: {},
179
- }, {}));
180
- };
181
- const transactionLines = async (ctx) => {
182
- const t = ctx.get(TX, at(ctx, 'transaction'));
183
- return t ? linePage(ctx, t) : txMissing(ctx, at(ctx, 'transaction'));
184
- };
185
- export const tax = {
186
- PostTaxRates: createRate,
187
- GetTaxRates: listRates,
188
- PostTaxRatesTaxRate: updateRate,
189
- GetTaxSettings: getSettings,
190
- PostTaxSettings: updateSettings,
191
- PostTaxCalculations: calculate,
192
- GetTaxCalculationsCalculationLineItems: calculationLines,
193
- PostTaxRegistrations: register,
194
- PostTaxTransactionsCreateFromCalculation: fromCalculation,
195
- PostTaxTransactionsCreateReversal: reversal,
196
- GetTaxTransactionsTransactionLineItems: transactionLines,
197
- };
@@ -1,5 +0,0 @@
1
- import type { Semantics, SemanticsContext } from '@volter/world-core';
2
- /** Time's settling of top-ups, caught up to the World's clock: a pending top-up succeeds on its expected_availability_date,
3
- * its funds entered then in the balance it names. */
4
- export declare function settleTopups(ctx: SemanticsContext): Promise<void>;
5
- export declare const terminal: Record<string, Semantics>;