@volter/twin-stripe 2.0.38 → 3.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (402) hide show
  1. package/README.md +112 -207
  2. package/dist/generated/pack-facts.json +94 -0
  3. package/dist/journeys/coverage.json +596 -0
  4. package/dist/journeys/customer-life.json +6108 -0
  5. package/dist/journeys/customer-life.outline.md +371 -0
  6. package/dist/journeys/decisions.json +677 -0
  7. package/dist/journeys/demand.json +706 -0
  8. package/dist/journeys/score.json +853 -0
  9. package/dist/journeys/unreachable.json +102 -0
  10. package/dist/journeys/vendor-examples.json +8010 -0
  11. package/dist/spec/SOURCE.md +18 -0
  12. package/dist/spec/doc-examples.json +445 -0
  13. package/dist/spec/fixtures3.json.gz +0 -0
  14. package/dist/spec/openapi.json.gz +0 -0
  15. package/dist/spec/patches.json +34 -0
  16. package/dist/spec/sources.json +306 -0
  17. package/dist/src/cli.d.ts +0 -1
  18. package/dist/src/cli.js +11 -31
  19. package/dist/src/engine/after-payment.d.ts +8 -0
  20. package/dist/src/engine/after-payment.js +27 -0
  21. package/dist/src/engine/apps-secrets.d.ts +1 -0
  22. package/dist/src/engine/apps-secrets.js +3 -0
  23. package/dist/src/engine/balance.d.ts +5 -0
  24. package/dist/src/engine/balance.js +15 -0
  25. package/dist/src/engine/checkout.d.ts +24 -0
  26. package/dist/src/engine/checkout.js +30 -0
  27. package/dist/src/engine/common.d.ts +19 -0
  28. package/dist/src/engine/common.js +34 -0
  29. package/dist/src/engine/connect.d.ts +45 -0
  30. package/dist/src/engine/connect.js +108 -0
  31. package/dist/src/engine/customers.d.ts +4 -0
  32. package/dist/src/engine/customers.js +8 -0
  33. package/dist/src/engine/display.d.ts +11 -0
  34. package/dist/src/engine/display.js +13 -0
  35. package/dist/src/engine/files.d.ts +11 -0
  36. package/dist/src/engine/files.js +23 -0
  37. package/dist/src/engine/invoices.d.ts +21 -0
  38. package/dist/src/engine/invoices.js +84 -0
  39. package/dist/src/engine/issuing.d.ts +33 -0
  40. package/dist/src/engine/issuing.js +54 -0
  41. package/dist/src/engine/ledger.d.ts +8 -0
  42. package/dist/src/engine/ledger.js +8 -0
  43. package/dist/src/engine/oauth.d.ts +4 -0
  44. package/dist/src/engine/oauth.js +24 -0
  45. package/dist/src/engine/onboarding.d.ts +13 -0
  46. package/dist/src/engine/onboarding.js +42 -0
  47. package/dist/src/{stripe-params.d.ts → engine/params.d.ts} +20 -3
  48. package/dist/src/{stripe-params.js → engine/params.js} +7 -60
  49. package/dist/src/engine/payment-intents.d.ts +10 -0
  50. package/dist/src/engine/payment-intents.js +27 -0
  51. package/dist/src/engine/payment-methods.d.ts +16 -0
  52. package/dist/src/engine/payment-methods.js +22 -0
  53. package/dist/src/engine/radar.d.ts +2 -0
  54. package/dist/src/engine/radar.js +5 -0
  55. package/dist/src/engine/refunds.d.ts +1 -0
  56. package/dist/src/engine/refunds.js +3 -0
  57. package/dist/src/engine/renewals.d.ts +36 -0
  58. package/dist/src/engine/renewals.js +65 -0
  59. package/dist/src/{stripe-twin.d.ts → engine/stripe.d.ts} +12 -45
  60. package/dist/src/{stripe-twin.js → engine/stripe.js} +53 -387
  61. package/dist/src/engine/subscriptions.d.ts +11 -0
  62. package/dist/src/engine/subscriptions.js +30 -0
  63. package/dist/src/engine/transfers.d.ts +2 -0
  64. package/dist/src/engine/transfers.js +1 -0
  65. package/dist/src/{stripe-version.d.ts → engine/version.d.ts} +0 -2
  66. package/dist/src/{stripe-version.js → engine/version.js} +21 -9
  67. package/dist/src/engine/webhook-endpoints.d.ts +1 -0
  68. package/dist/src/engine/webhook-endpoints.js +12 -0
  69. package/dist/src/engine/webhooks.d.ts +31 -0
  70. package/dist/src/engine/webhooks.js +68 -0
  71. package/dist/src/fetch.d.ts +2 -0
  72. package/dist/src/fetch.js +26 -0
  73. package/dist/src/generated/surface.gen.json +1 -1
  74. package/dist/src/generated/ui.gen.json +1 -1
  75. package/dist/src/index.d.ts +5 -14
  76. package/dist/src/index.js +10 -75
  77. package/dist/src/manifest.js +478 -876
  78. package/dist/src/screens/billing-portal.d.ts +3 -0
  79. package/dist/src/screens/{portal.js → billing-portal.js} +32 -58
  80. package/dist/src/screens/checkout-js.d.ts +2 -0
  81. package/dist/src/screens/checkout-js.js +84 -0
  82. package/dist/src/screens/checkout.d.ts +2 -31
  83. package/dist/src/screens/checkout.js +32 -121
  84. package/dist/src/screens/connect-onboarding.d.ts +3 -0
  85. package/dist/src/screens/{onboarding.js → connect-onboarding.js} +38 -104
  86. package/dist/src/screens/dashboard.d.ts +3 -0
  87. package/dist/src/screens/dashboard.js +116 -0
  88. package/dist/src/screens/shared.d.ts +27 -0
  89. package/dist/src/screens/shared.js +87 -0
  90. package/dist/src/screens/stripe-js.d.ts +3 -0
  91. package/dist/src/screens/stripe-js.js +95 -0
  92. package/dist/src/semantics/account.d.ts +2 -0
  93. package/dist/src/semantics/account.js +8 -0
  94. package/dist/src/semantics/account_links.d.ts +2 -0
  95. package/dist/src/semantics/account_links.js +22 -0
  96. package/dist/src/semantics/accounts.d.ts +4 -0
  97. package/dist/src/semantics/accounts.js +40 -0
  98. package/dist/src/semantics/apps.d.ts +4 -0
  99. package/dist/src/semantics/{apps-secrets.js → apps.js} +14 -26
  100. package/dist/src/semantics/around.d.ts +2 -0
  101. package/dist/src/semantics/around.js +13 -0
  102. package/dist/src/semantics/balance.d.ts +2 -11
  103. package/dist/src/semantics/balance.js +3 -194
  104. package/dist/src/semantics/balance_transactions.d.ts +2 -0
  105. package/dist/src/semantics/balance_transactions.js +15 -0
  106. package/dist/src/semantics/billing_portal.d.ts +4 -0
  107. package/dist/src/semantics/billing_portal.js +36 -0
  108. package/dist/src/semantics/charges.d.ts +3 -28
  109. package/dist/src/semantics/charges.js +5 -202
  110. package/dist/src/semantics/checkout.d.ts +3 -20
  111. package/dist/src/semantics/checkout.js +21 -271
  112. package/dist/src/semantics/clock.d.ts +2 -0
  113. package/dist/src/semantics/clock.js +15 -0
  114. package/dist/src/semantics/coupons.d.ts +2 -6
  115. package/dist/src/semantics/coupons.js +2 -60
  116. package/dist/src/semantics/customers.d.ts +5 -6
  117. package/dist/src/semantics/customers.js +47 -413
  118. package/dist/src/semantics/doors.d.ts +23 -0
  119. package/dist/src/semantics/doors.js +73 -0
  120. package/dist/src/semantics/entitlements.d.ts +0 -2
  121. package/dist/src/semantics/entitlements.js +4 -95
  122. package/dist/src/semantics/events.d.ts +11 -0
  123. package/dist/src/semantics/events.js +31 -0
  124. package/dist/src/semantics/index.d.ts +2 -0
  125. package/dist/src/semantics/index.js +85 -0
  126. package/dist/src/semantics/invoice_payments.d.ts +2 -0
  127. package/dist/src/semantics/invoice_payments.js +12 -0
  128. package/dist/src/semantics/invoices.d.ts +11 -18
  129. package/dist/src/semantics/invoices.js +121 -440
  130. package/dist/src/semantics/issuing.d.ts +6 -13
  131. package/dist/src/semantics/issuing.js +58 -556
  132. package/dist/src/semantics/payment_intents.d.ts +3 -0
  133. package/dist/src/semantics/payment_intents.js +71 -0
  134. package/dist/src/semantics/payment_methods.d.ts +3 -0
  135. package/dist/src/semantics/payment_methods.js +15 -0
  136. package/dist/src/semantics/payouts.d.ts +3 -0
  137. package/dist/src/semantics/payouts.js +28 -0
  138. package/dist/src/semantics/prices.d.ts +4 -0
  139. package/dist/src/semantics/prices.js +37 -0
  140. package/dist/src/semantics/products.d.ts +4 -2
  141. package/dist/src/semantics/products.js +12 -138
  142. package/dist/src/semantics/promotion_codes.d.ts +3 -0
  143. package/dist/src/semantics/promotion_codes.js +35 -0
  144. package/dist/src/semantics/radar.d.ts +2 -2
  145. package/dist/src/semantics/radar.js +5 -74
  146. package/dist/src/semantics/refunds.d.ts +2 -9
  147. package/dist/src/semantics/refunds.js +3 -193
  148. package/dist/src/semantics/shared.d.ts +558 -55
  149. package/dist/src/semantics/shared.js +2070 -114
  150. package/dist/src/semantics/states.d.ts +462 -0
  151. package/dist/src/semantics/states.js +634 -0
  152. package/dist/src/semantics/subscriptions.d.ts +6 -11
  153. package/dist/src/semantics/subscriptions.js +37 -530
  154. package/dist/src/semantics/test_helpers.d.ts +3 -0
  155. package/dist/src/semantics/test_helpers.js +125 -0
  156. package/dist/src/semantics/transfers.d.ts +2 -2
  157. package/dist/src/semantics/transfers.js +6 -101
  158. package/dist/src/semantics/webhook_endpoints.d.ts +2 -0
  159. package/dist/src/semantics/webhook_endpoints.js +26 -0
  160. package/dist/src/server.d.ts +7 -0
  161. package/dist/src/server.js +7 -0
  162. package/generated/pack-facts.json +94 -0
  163. package/journeys/coverage.json +596 -0
  164. package/journeys/customer-life.json +6108 -0
  165. package/journeys/customer-life.outline.md +371 -0
  166. package/journeys/decisions.json +677 -0
  167. package/journeys/demand.json +706 -0
  168. package/journeys/score.json +853 -0
  169. package/journeys/unreachable.json +102 -0
  170. package/journeys/vendor-examples.json +8010 -0
  171. package/package.json +11 -20
  172. package/spec/SOURCE.md +18 -0
  173. package/spec/doc-examples.json +445 -0
  174. package/spec/fixtures3.json.gz +0 -0
  175. package/spec/openapi.json.gz +0 -0
  176. package/spec/patches.json +34 -0
  177. package/spec/sources.json +306 -0
  178. package/src/cli.ts +11 -28
  179. package/src/engine/after-payment.ts +29 -0
  180. package/src/engine/apps-secrets.ts +4 -0
  181. package/src/engine/balance.ts +32 -0
  182. package/src/engine/checkout.ts +39 -0
  183. package/src/engine/common.ts +49 -0
  184. package/src/engine/connect.ts +106 -0
  185. package/src/engine/customers.ts +10 -0
  186. package/src/engine/display.ts +18 -0
  187. package/src/engine/files.ts +28 -0
  188. package/src/engine/invoices.ts +102 -0
  189. package/src/engine/issuing.ts +66 -0
  190. package/src/engine/ledger.ts +48 -0
  191. package/src/engine/oauth.ts +18 -0
  192. package/src/engine/onboarding.ts +53 -0
  193. package/src/{stripe-params.ts → engine/params.ts} +7 -56
  194. package/src/engine/payment-intents.ts +32 -0
  195. package/src/engine/payment-methods.ts +24 -0
  196. package/src/engine/radar.ts +6 -0
  197. package/src/engine/refunds.ts +3 -0
  198. package/src/engine/renewals.ts +72 -0
  199. package/src/{stripe-twin.ts → engine/stripe.ts} +57 -400
  200. package/src/engine/subscriptions.ts +37 -0
  201. package/src/engine/transfers.ts +22 -0
  202. package/src/{stripe-version.ts → engine/version.ts} +19 -10
  203. package/src/engine/webhook-endpoints.ts +14 -0
  204. package/src/engine/webhooks.ts +70 -0
  205. package/src/fetch.ts +27 -0
  206. package/src/generated/surface.gen.json +1 -1
  207. package/src/generated/ui.gen.json +1 -1
  208. package/src/index.ts +10 -116
  209. package/src/manifest.ts +480 -904
  210. package/src/screens/{portal.tsx → billing-portal.tsx} +35 -42
  211. package/src/screens/checkout-js.ts +80 -0
  212. package/src/screens/checkout.tsx +32 -96
  213. package/src/screens/{onboarding.tsx → connect-onboarding.tsx} +39 -85
  214. package/src/screens/dashboard.tsx +178 -0
  215. package/src/screens/shared.tsx +84 -0
  216. package/src/screens/stripe-js.ts +102 -0
  217. package/src/semantics/account.ts +10 -0
  218. package/src/semantics/account_links.ts +20 -0
  219. package/src/semantics/accounts.ts +44 -0
  220. package/src/semantics/{apps-secrets.ts → apps.ts} +17 -33
  221. package/src/semantics/around.ts +17 -0
  222. package/src/semantics/balance.ts +6 -208
  223. package/src/semantics/balance_transactions.ts +18 -0
  224. package/src/semantics/billing_portal.ts +45 -0
  225. package/src/semantics/charges.ts +8 -212
  226. package/src/semantics/checkout.ts +25 -276
  227. package/src/semantics/clock.ts +19 -0
  228. package/src/semantics/coupons.ts +5 -68
  229. package/src/semantics/customers.ts +48 -414
  230. package/src/semantics/doors.ts +79 -0
  231. package/src/semantics/entitlements.ts +3 -94
  232. package/src/semantics/events.ts +37 -0
  233. package/src/semantics/index.ts +89 -0
  234. package/src/semantics/invoice_payments.ts +16 -0
  235. package/src/semantics/invoices.ts +112 -441
  236. package/src/semantics/issuing.ts +57 -573
  237. package/src/semantics/payment_intents.ts +76 -0
  238. package/src/semantics/payment_methods.ts +20 -0
  239. package/src/semantics/payouts.ts +29 -0
  240. package/src/semantics/prices.ts +41 -0
  241. package/src/semantics/products.ts +12 -146
  242. package/src/semantics/promotion_codes.ts +38 -0
  243. package/src/semantics/radar.ts +8 -79
  244. package/src/semantics/refunds.ts +4 -216
  245. package/src/semantics/shared.ts +2089 -135
  246. package/src/semantics/states.ts +662 -0
  247. package/src/semantics/subscriptions.ts +39 -542
  248. package/src/semantics/test_helpers.ts +119 -0
  249. package/src/semantics/transfers.ts +10 -132
  250. package/src/semantics/webhook_endpoints.ts +27 -0
  251. package/src/server.ts +7 -0
  252. package/client/dashboard-api.ts +0 -286
  253. package/client/stripe-mirror.css +0 -277
  254. package/client/stripe-mirror.tsx +0 -1559
  255. package/dist/client/dashboard-api.d.ts +0 -107
  256. package/dist/client/dashboard-api.js +0 -238
  257. package/dist/client/dashboard-api.ts +0 -286
  258. package/dist/client/stripe-mirror.bundle.js +0 -236
  259. package/dist/client/stripe-mirror.css +0 -277
  260. package/dist/client/stripe-mirror.d.ts +0 -134
  261. package/dist/client/stripe-mirror.js +0 -859
  262. package/dist/client/stripe-mirror.tsx +0 -1559
  263. package/dist/src/screens/connect-oauth.d.ts +0 -27
  264. package/dist/src/screens/connect-oauth.js +0 -414
  265. package/dist/src/screens/connect-settings.d.ts +0 -22
  266. package/dist/src/screens/connect-settings.js +0 -103
  267. package/dist/src/screens/consent-skin.d.ts +0 -4
  268. package/dist/src/screens/consent-skin.js +0 -18
  269. package/dist/src/screens/financial-connections.d.ts +0 -5
  270. package/dist/src/screens/financial-connections.js +0 -90
  271. package/dist/src/screens/identity.d.ts +0 -5
  272. package/dist/src/screens/identity.js +0 -86
  273. package/dist/src/screens/onboarding.d.ts +0 -13
  274. package/dist/src/screens/portal.d.ts +0 -5
  275. package/dist/src/screens/public-details.d.ts +0 -5
  276. package/dist/src/screens/public-details.js +0 -90
  277. package/dist/src/semantics/after-payment.d.ts +0 -22
  278. package/dist/src/semantics/after-payment.js +0 -99
  279. package/dist/src/semantics/apps-secrets.d.ts +0 -2
  280. package/dist/src/semantics/billing.d.ts +0 -2
  281. package/dist/src/semantics/billing.js +0 -220
  282. package/dist/src/semantics/connect.d.ts +0 -5
  283. package/dist/src/semantics/connect.js +0 -493
  284. package/dist/src/semantics/credit-notes.d.ts +0 -2
  285. package/dist/src/semantics/credit-notes.js +0 -172
  286. package/dist/src/semantics/disputes.d.ts +0 -2
  287. package/dist/src/semantics/disputes.js +0 -51
  288. package/dist/src/semantics/ephemeral-keys.d.ts +0 -2
  289. package/dist/src/semantics/ephemeral-keys.js +0 -34
  290. package/dist/src/semantics/files.d.ts +0 -2
  291. package/dist/src/semantics/files.js +0 -125
  292. package/dist/src/semantics/ledger.d.ts +0 -59
  293. package/dist/src/semantics/ledger.js +0 -200
  294. package/dist/src/semantics/payment-intents.d.ts +0 -18
  295. package/dist/src/semantics/payment-intents.js +0 -452
  296. package/dist/src/semantics/payment-links.d.ts +0 -2
  297. package/dist/src/semantics/payment-links.js +0 -133
  298. package/dist/src/semantics/payment-methods.d.ts +0 -20
  299. package/dist/src/semantics/payment-methods.js +0 -140
  300. package/dist/src/semantics/plans.d.ts +0 -5
  301. package/dist/src/semantics/plans.js +0 -121
  302. package/dist/src/semantics/platform.d.ts +0 -9
  303. package/dist/src/semantics/platform.js +0 -206
  304. package/dist/src/semantics/renewals.d.ts +0 -47
  305. package/dist/src/semantics/renewals.js +0 -281
  306. package/dist/src/semantics/setup-intents.d.ts +0 -2
  307. package/dist/src/semantics/setup-intents.js +0 -84
  308. package/dist/src/semantics/subscription-schedules.d.ts +0 -2
  309. package/dist/src/semantics/subscription-schedules.js +0 -119
  310. package/dist/src/semantics/tax.d.ts +0 -2
  311. package/dist/src/semantics/tax.js +0 -197
  312. package/dist/src/semantics/terminal.d.ts +0 -5
  313. package/dist/src/semantics/terminal.js +0 -182
  314. package/dist/src/semantics/test-clocks.d.ts +0 -6
  315. package/dist/src/semantics/test-clocks.js +0 -73
  316. package/dist/src/semantics/tokens.d.ts +0 -4
  317. package/dist/src/semantics/tokens.js +0 -44
  318. package/dist/src/semantics/treasury.d.ts +0 -2
  319. package/dist/src/semantics/treasury.js +0 -377
  320. package/dist/src/semantics/webhook-endpoints.d.ts +0 -3
  321. package/dist/src/semantics/webhook-endpoints.js +0 -85
  322. package/dist/src/stripe-budget.d.ts +0 -55
  323. package/dist/src/stripe-budget.js +0 -155
  324. package/dist/src/stripe-capabilities.d.ts +0 -3
  325. package/dist/src/stripe-capabilities.js +0 -5836
  326. package/dist/src/stripe-conformance.d.ts +0 -43
  327. package/dist/src/stripe-conformance.js +0 -105
  328. package/dist/src/stripe-connector.d.ts +0 -161
  329. package/dist/src/stripe-connector.js +0 -414
  330. package/dist/src/stripe-emit.d.ts +0 -2
  331. package/dist/src/stripe-emit.js +0 -145
  332. package/dist/src/stripe-events.d.ts +0 -93
  333. package/dist/src/stripe-events.js +0 -392
  334. package/dist/src/stripe-js.d.ts +0 -4
  335. package/dist/src/stripe-js.js +0 -70
  336. package/dist/src/stripe-mirror-ui.d.ts +0 -15
  337. package/dist/src/stripe-mirror-ui.js +0 -87
  338. package/dist/src/stripe-perform-harness.d.ts +0 -9
  339. package/dist/src/stripe-perform-harness.js +0 -26
  340. package/dist/src/stripe-server.d.ts +0 -33
  341. package/dist/src/stripe-server.js +0 -429
  342. package/dist/src/stripe-shared.d.ts +0 -109
  343. package/dist/src/stripe-shared.js +0 -276
  344. package/dist/src/stripe-ui-conformance.d.ts +0 -5
  345. package/dist/src/stripe-ui-conformance.js +0 -79
  346. package/dist/src/stripe-ui-structure.d.ts +0 -3
  347. package/dist/src/stripe-ui-structure.js +0 -168
  348. package/dist/test-fixtures/stripe-known-deviations.json +0 -110
  349. package/dist/test-fixtures/stripe-openapi-operations.SOURCE.md +0 -14
  350. package/dist/test-fixtures/stripe-openapi-operations.json +0 -4717
  351. package/dist/test-fixtures/stripe-schemas.SOURCE.md +0 -35
  352. package/dist/test-fixtures/stripe-schemas.json +0 -3813
  353. package/src/screens/connect-oauth.tsx +0 -400
  354. package/src/screens/connect-settings.tsx +0 -121
  355. package/src/screens/consent-skin.ts +0 -20
  356. package/src/screens/financial-connections.tsx +0 -101
  357. package/src/screens/identity.tsx +0 -96
  358. package/src/screens/public-details.tsx +0 -105
  359. package/src/semantics/after-payment.ts +0 -118
  360. package/src/semantics/billing.ts +0 -216
  361. package/src/semantics/connect.ts +0 -487
  362. package/src/semantics/credit-notes.ts +0 -168
  363. package/src/semantics/disputes.ts +0 -62
  364. package/src/semantics/ephemeral-keys.ts +0 -34
  365. package/src/semantics/files.ts +0 -143
  366. package/src/semantics/ledger.ts +0 -253
  367. package/src/semantics/payment-intents.ts +0 -463
  368. package/src/semantics/payment-links.ts +0 -148
  369. package/src/semantics/payment-methods.ts +0 -145
  370. package/src/semantics/plans.ts +0 -131
  371. package/src/semantics/platform.ts +0 -220
  372. package/src/semantics/renewals.ts +0 -279
  373. package/src/semantics/setup-intents.ts +0 -87
  374. package/src/semantics/subscription-schedules.ts +0 -129
  375. package/src/semantics/tax.ts +0 -220
  376. package/src/semantics/terminal.ts +0 -195
  377. package/src/semantics/test-clocks.ts +0 -77
  378. package/src/semantics/tokens.ts +0 -52
  379. package/src/semantics/treasury.ts +0 -383
  380. package/src/semantics/webhook-endpoints.ts +0 -87
  381. package/src/stripe-budget.ts +0 -181
  382. package/src/stripe-capabilities.ts +0 -5651
  383. package/src/stripe-conformance.ts +0 -124
  384. package/src/stripe-connector.ts +0 -462
  385. package/src/stripe-emit.ts +0 -157
  386. package/src/stripe-events.ts +0 -434
  387. package/src/stripe-js.ts +0 -70
  388. package/src/stripe-mirror-ui.ts +0 -90
  389. package/src/stripe-perform-harness.ts +0 -29
  390. package/src/stripe-server.ts +0 -393
  391. package/src/stripe-shared.ts +0 -297
  392. package/src/stripe-ui-conformance.ts +0 -88
  393. package/src/stripe-ui-structure.ts +0 -182
  394. package/test-fixtures/stripe-known-deviations.json +0 -110
  395. package/test-fixtures/stripe-openapi-operations.json +0 -4717
  396. package/test-fixtures/stripe-schemas.json +0 -3813
  397. /package/dist/src/{screens → engine}/industries.d.ts +0 -0
  398. /package/dist/src/{screens → engine}/industries.js +0 -0
  399. /package/dist/src/{semantics → engine}/test-cards.d.ts +0 -0
  400. /package/dist/src/{semantics → engine}/test-cards.js +0 -0
  401. /package/src/{screens → engine}/industries.ts +0 -0
  402. /package/src/{semantics → engine}/test-cards.ts +0 -0
@@ -1,168 +0,0 @@
1
- // Credit note semantics. A credit note credits part of an invoice: pre_payment while the invoice
2
- // is unpaid (it lowers what is owed), post_payment once paid. The invoice carries the sums of its
3
- // issued credit notes, re-derived on every change so voiding one returns the invoice to where it
4
- // was. The machine in ../manifest.ts says a credit note is voided once. The list is the derived core's.
5
- import type { Semantics, SemanticsContext } from '@volter/world-core';
6
- import { paginate } from '../stripe-twin.ts';
7
- import { refundCharge } from './refunds.ts';
8
- import { at, created, fail, path, type Row } from './shared.ts';
9
-
10
- const CN = 'credit_note';
11
- const noteMissing = (ctx: SemanticsContext, id: string): Response => fail(ctx, `No such credit note: '${id}'`, 404, 'resource_missing');
12
-
13
- /** The credit note the request describes (the `amount` form: one custom line), or Stripe's refusal. */
14
- function build(ctx: SemanticsContext, id: string): Row | Response {
15
- const params = ctx.params;
16
- const invoiceId = typeof params.invoice === 'string' ? params.invoice : '';
17
- if (!invoiceId) return fail(ctx, 'Missing required param: invoice.', 400, 'parameter_missing');
18
- const invoice = ctx.get('invoice', invoiceId);
19
- if (!invoice) return fail(ctx, `No such invoice: '${invoiceId}'`, 404, 'resource_missing');
20
- if (params.amount === undefined) return fail(ctx, 'Missing required param: amount.', 400, 'parameter_missing');
21
- const amount = Number(params.amount);
22
- if (!Number.isInteger(amount) || amount <= 0) return fail(ctx, 'Invalid integer: amount must be a positive integer.', 400, 'parameter_invalid_integer');
23
- const vendorType = invoice.status === 'paid' ? 'post_payment' : 'pre_payment';
24
- const outOfBand = Number(params.out_of_band_amount) || 0;
25
- // a paid invoice's credit is paid back: "The sum of refunds, customer balance credits, and outside of Stripe credits
26
- // must equal the post_payment_amount" (docs.stripe.com/api/credit_notes/create); the message's wording is the twin's
27
- if (vendorType === 'post_payment') {
28
- const split = (Number(params.refund_amount) || 0) + (Number(params.credit_amount) || 0) + outOfBand;
29
- if (split !== amount) return fail(ctx, `The sum of refund_amount, credit_amount and out_of_band_amount (${split}) must equal the credit note's post_payment_amount (${amount}).`, 400, 'parameter_invalid_integer');
30
- }
31
- const line = {
32
- object: 'credit_note_line_item', id: `cnli_${id}_1`, type: 'custom_line_item',
33
- amount, description: typeof params.memo === 'string' ? params.memo : null,
34
- // a custom line credits no invoice line: invoice_line_item ("ID of the invoice line item being credited") is left
35
- // out, the served spec not letting it be null
36
- discount_amount: 0, discount_amounts: [], livemode: false,
37
- pretax_credit_amounts: [], quantity: null, tax_rates: [], taxes: [],
38
- unit_amount: null, unit_amount_decimal: null,
39
- };
40
- return {
41
- amount, amount_shipping: 0, created: ctx.now(), currency: typeof invoice.currency === 'string' ? invoice.currency : 'usd', customer: typeof invoice.customer === 'string' ? invoice.customer : null,
42
- customer_balance_transaction: null,
43
- // "The date when this credit note is in effect. Same as `created` unless overwritten" (the served spec)
44
- discount_amount: 0, discount_amounts: [], effective_at: params.effective_at !== undefined ? Number(params.effective_at) : ctx.now(), invoice: invoiceId,
45
- lines: { object: 'list', data: [line], has_more: false, total_count: 1, url: `/v1/credit_notes/${id}/lines` },
46
- livemode: false, memo: params.memo ?? null, metadata: params.metadata && typeof params.metadata === 'object' ? params.metadata : {},
47
- number: `${invoiceId}-CN-01`, out_of_band_amount: outOfBand || null,
48
- pdf: `https://files.twin.local/credit_notes/${id}.pdf`,
49
- post_payment_amount: vendorType === 'post_payment' ? amount : 0,
50
- pre_payment_amount: vendorType === 'pre_payment' ? amount : 0,
51
- pretax_credit_amounts: [],
52
- reason: typeof params.reason === 'string' ? params.reason : null,
53
- refunds: [], shipping_cost: null, status: 'issued',
54
- subtotal: amount, subtotal_excluding_tax: amount,
55
- type: vendorType, total: amount, total_excluding_tax: amount, total_taxes: [],
56
- voided_at: null,
57
- };
58
- }
59
-
60
- /** The invoice's credit-note sums, from its issued credit notes; a pre-payment credit lowers what is owed. */
61
- async function syncInvoice(ctx: SemanticsContext, invoiceId: string): Promise<void> {
62
- const inv = ctx.get('invoice', invoiceId);
63
- if (!inv) return;
64
- let pre = 0;
65
- let post = 0;
66
- for (const cn of ctx.rows(CN)) {
67
- if (cn.invoice !== invoiceId || cn.status === 'void') continue;
68
- if (cn.type === 'post_payment') post += Number(cn.amount) || 0;
69
- else pre += Number(cn.amount) || 0;
70
- }
71
- const total = Number(inv.total ?? inv.amount_due) || 0;
72
- const paid = Number(inv.amount_paid) || 0;
73
- await ctx.write('invoice', invoiceId, { pre_payment_credit_notes_amount: pre, post_payment_credit_notes_amount: post, amount_remaining: Math.max(0, total - paid - pre) }, 'invoice.update');
74
- }
75
-
76
- // the preview computes the credit note without keeping it
77
- const preview: Semantics = async (ctx) => {
78
- const id = 'cn_preview';
79
- const cn = build(ctx, id);
80
- return cn instanceof Response ? cn : ctx.reply({ object: CN, ...cn, id });
81
- };
82
-
83
- /** What a post-payment credit pays back: "Refunds: create a new refund (using refund_amount)"; "Customer balance credit:
84
- * credit the customer's balance (using credit_amount) which will be automatically applied to their next invoice when
85
- * it's finalized" (docs.stripe.com/api/credit_notes/create). The refund is made on the invoice's charge as a refund
86
- * call makes it (refunds.ts); the credit is a customer balance transaction of type credit_note. Where the documentation
87
- * stops and the twin decides: the refund carries no reason of its own. */
88
- async function payBack(ctx: SemanticsContext, id: string, cn: Row): Promise<Row | Response> {
89
- const params = ctx.params;
90
- const out: Row = {};
91
- const refundAmount = Number(params.refund_amount) || 0;
92
- if (refundAmount > 0) {
93
- const invoice = ctx.get('invoice', String(cn.invoice));
94
- const pi = typeof invoice?.payment_intent === 'string' ? ctx.get('payment_intent', invoice.payment_intent) : undefined;
95
- const chargeId = typeof invoice?.charge === 'string' ? invoice.charge : typeof pi?.latest_charge === 'string' ? pi.latest_charge : undefined;
96
- const charge = chargeId ? ctx.get('charge', chargeId) : undefined;
97
- if (!charge) return fail(ctx, 'This invoice was not paid with a charge that can be refunded.', 400, 'invoice_no_charge_to_refund');
98
- const answer = await refundCharge(ctx, charge, { amount: refundAmount });
99
- if (answer.status >= 400) return answer;
100
- const refund = (await answer.json()) as Row;
101
- out.refunds = [{ amount_refunded: refundAmount, refund: refund.id, type: 'refund', payment_record_refund: null }];
102
- }
103
- const creditAmount = Number(params.credit_amount) || 0;
104
- const customer = typeof cn.customer === 'string' ? cn.customer : undefined;
105
- if (creditAmount > 0 && customer) {
106
- const ending = (Number(ctx.get('customer', customer)?.balance) || 0) - creditAmount;
107
- const txn = await created(ctx, 'customer_balance_transaction', { customer, amount: -creditAmount, currency: cn.currency, credit_note: id, invoice: cn.invoice }, {
108
- ending_balance: ending, type: 'credit_note', livemode: false, metadata: {}, description: null, checkout_session: null,
109
- });
110
- await ctx.write('customer', customer, { balance: ending }, `customer.balance_adjusted:${String(txn.id)}`);
111
- out.customer_balance_transaction = txn.id;
112
- }
113
- return out;
114
- }
115
-
116
- const create: Semantics = async (ctx) => {
117
- const id = ctx.mint(CN);
118
- const cn = build(ctx, id);
119
- if (cn instanceof Response) return cn;
120
- const paid = cn.type === 'post_payment' ? await payBack(ctx, id, cn) : {};
121
- if (paid instanceof Response) return paid;
122
- const body = await created(ctx, CN, { id, ...cn, ...paid }, {});
123
- await syncInvoice(ctx, String(cn.invoice));
124
- return ctx.reply(body);
125
- };
126
-
127
- const retrieve: Semantics = async (ctx) => {
128
- const c = ctx.get(CN, at(ctx, 'id'));
129
- return c ? ctx.reply(c) : noteMissing(ctx, at(ctx, 'id'));
130
- };
131
-
132
- const lines: Semantics = async (ctx) => {
133
- const c = ctx.get(CN, at(ctx, 'credit_note'));
134
- if (!c) return noteMissing(ctx, at(ctx, 'credit_note'));
135
- const l = c.lines as { data?: Row[] } | undefined;
136
- const { page, hasMore } = paginate(Array.isArray(l?.data) ? l!.data! : [], ctx.params);
137
- return ctx.reply({ object: 'list', url: path(ctx), has_more: hasMore, data: page });
138
- };
139
-
140
- const voidNote: Semantics = async (ctx) => {
141
- const id = at(ctx, 'id');
142
- const c = ctx.get(CN, id);
143
- if (!c) return noteMissing(ctx, id);
144
- const refused = ctx.legal(CN, 'status', 'PostCreditNotesIdVoid', c.status, undefined, id);
145
- if (refused) return ctx.refuse(refused);
146
- const voided = await ctx.write(CN, id, { status: 'void', voided_at: ctx.now() }, 'credit_note.void');
147
- if (typeof c.invoice === 'string') await syncInvoice(ctx, c.invoice);
148
- return ctx.reply(voided);
149
- };
150
-
151
- // only the memo and metadata change
152
- const update: Semantics = async (ctx) => {
153
- const id = at(ctx, 'id');
154
- if (!ctx.get(CN, id)) return noteMissing(ctx, id);
155
- const patch: Row = {};
156
- if (ctx.params.memo !== undefined) patch.memo = ctx.params.memo;
157
- if (ctx.params.metadata !== undefined) patch.metadata = ctx.params.metadata;
158
- return ctx.reply(await ctx.write(CN, id, patch, 'credit_note.update'));
159
- };
160
-
161
- export const creditNotes: Record<string, Semantics> = {
162
- GetCreditNotesPreview: preview,
163
- PostCreditNotes: create,
164
- GetCreditNotesId: retrieve,
165
- GetCreditNotesCreditNoteLines: lines,
166
- PostCreditNotesIdVoid: voidNote,
167
- PostCreditNotesId: update,
168
- };
@@ -1,62 +0,0 @@
1
- // Dispute semantics. A dispute is Stripe's to open, when a charge's cardholder disputes it: the test cards
2
- // that are disputed open one as their charge succeeds (./after-payment.ts). It is then listed, retrieved,
3
- // updated with evidence and closed. Closing concedes it (status → lost), the machine's move in
4
- // ../manifest.ts. Evidence is submitted with the update unless `submit` is false
5
- // (docs.stripe.com/api/disputes/update#update_dispute-submit), and the bank then decides it: in test mode, evidence whose
6
- // uncategorized_text is `winning_evidence` wins it and `losing_evidence` loses it (docs.stripe.com/testing#evidence);
7
- // a won dispute returns the disputed amount. Where the documentation stops and the twin decides: the bank decides at
8
- // once, and any other evidence leaves the dispute under review. List is the derived core's.
9
- import type { Semantics, SemanticsContext } from '@volter/world-core';
10
- import { asBool } from '../stripe-twin.ts';
11
- import { settleDisputeWon } from './ledger.ts';
12
- import { at, fail, type Row } from './shared.ts';
13
-
14
- const disputeMissing = (ctx: SemanticsContext, id: string): Response => fail(ctx, `No such dispute: '${id}'`, 404, 'resource_missing');
15
-
16
- const retrieve: Semantics = async (ctx) => {
17
- const d = ctx.get('dispute', at(ctx, 'dispute'));
18
- return d ? ctx.reply(d) : disputeMissing(ctx, at(ctx, 'dispute'));
19
- };
20
-
21
- const close: Semantics = async (ctx) => {
22
- const id = at(ctx, 'dispute');
23
- const d = ctx.get('dispute', id);
24
- if (!d) return disputeMissing(ctx, id);
25
- const refused = ctx.legal('dispute', 'status', 'PostDisputesDisputeClose', d.status, undefined, id);
26
- if (refused) return ctx.refuse(refused);
27
- return ctx.reply(await ctx.write('dispute', id, { status: 'lost' }, 'dispute.close'));
28
- };
29
-
30
- /** Evidence staged without submitting it (submit=false), or on a dispute already under review or decided. */
31
- async function keepEvidence(ctx: SemanticsContext, id: string, fields: Row): Promise<Response> {
32
- return ctx.reply(await ctx.write('dispute', id, fields, 'dispute.update'));
33
- }
34
-
35
- const update: Semantics = async (ctx) => {
36
- const id = at(ctx, 'dispute');
37
- const d = ctx.get('dispute', id);
38
- if (!d) return disputeMissing(ctx, id);
39
- const params = ctx.params;
40
- const given = params.evidence && typeof params.evidence === 'object' ? (params.evidence as Row) : {};
41
- const evidence = { ...((d.evidence as Row | undefined) ?? {}), ...given };
42
- const fields: Row = { evidence, ...(params.metadata && typeof params.metadata === 'object' ? { metadata: { ...((d.metadata as Row | undefined) ?? {}), ...(params.metadata as Row) } } : {}) };
43
- const submit = params.submit === undefined ? true : asBool(params.submit);
44
- const review = d.status === 'warning_needs_response' ? 'warning_under_review' : 'under_review';
45
- if (!submit || ctx.legal('dispute', 'status', 'PostDisputesDispute', d.status, review, id)) return keepEvidence(ctx, id, fields);
46
- const details = (d.evidence_details as Row | undefined) ?? {};
47
- let body = await ctx.write('dispute', id, { ...fields, status: review, evidence_details: { ...details, has_evidence: true, submission_count: (Number(details.submission_count) || 0) + 1 } }, 'charge.dispute.updated');
48
- const text = String(evidence.uncategorized_text ?? '');
49
- const decided = review === 'under_review' ? (text.includes('winning_evidence') ? 'won' : text.includes('losing_evidence') ? 'lost' : undefined) : undefined;
50
- if (decided && !ctx.legal('dispute', 'status', 'PostDisputesDispute', review, decided, id, 'vendor')) {
51
- const bt = decided === 'won' ? await settleDisputeWon(ctx, id, Number(d.amount) || 0, String(d.currency ?? 'usd')) : undefined;
52
- const kept = ((ctx.get('dispute', id)?.balance_transactions as unknown[] | undefined) ?? []);
53
- body = await ctx.write('dispute', id, { status: decided, ...(bt ? { balance_transactions: [...kept, ctx.get('balance_transaction', bt) ?? bt] } : {}) }, 'charge.dispute.closed');
54
- }
55
- return ctx.reply(body);
56
- };
57
-
58
- export const disputes: Record<string, Semantics> = {
59
- GetDisputesDispute: retrieve,
60
- PostDisputesDispute: update,
61
- PostDisputesDisputeClose: close,
62
- };
@@ -1,34 +0,0 @@
1
- // Ephemeral key semantics: the short-lived key the mobile SDKs use, scoped to exactly one object.
2
- // It needs the Stripe-Version header; its secret is answered only by the create; deleting it
3
- // expires it early.
4
- import type { Semantics } from '@volter/world-core';
5
- import { at, fail } from './shared.ts';
6
-
7
- const create: Semantics = async (ctx) => {
8
- const version = ctx.call.request.headers.get('stripe-version');
9
- if (!version) return fail(ctx, 'You must pass the `Stripe-Version` header (e.g. via the apiVersion option) when creating an ephemeral key.', 400, 'parameter_missing');
10
- const params = ctx.params;
11
- const scopes: Array<[string, string]> = [];
12
- if (typeof params.customer === 'string' && params.customer) scopes.push(['customer', params.customer]);
13
- if (typeof params.issuing_card === 'string' && params.issuing_card) scopes.push(['issuing.card', params.issuing_card]);
14
- if (typeof params.verification_session === 'string' && params.verification_session) scopes.push(['identity.verification_session', params.verification_session]);
15
- if (scopes.length !== 1) return fail(ctx, 'You must pass exactly one of `customer`, `issuing_card`, or `verification_session`.', 400, 'parameter_missing');
16
- const [scope, scopedId] = scopes[0]!;
17
- if (scope === 'customer' && !ctx.get('customer', scopedId)) return fail(ctx, `No such customer: '${scopedId}'`, 400, 'resource_missing');
18
- const id = ctx.mint('ephemeral_key');
19
- const now = Number(ctx.now());
20
- const associated_objects = [{ type: scope, id: scopedId }];
21
- await ctx.write('ephemeral_key', id, { object: 'ephemeral_key', created: now, expires: now + 3600, livemode: false, associated_objects }, 'ephemeral_key.create');
22
- return ctx.reply({ id, object: 'ephemeral_key', created: now, expires: now + 3600, livemode: false, secret: `ek_test_twin_${id}`, associated_objects });
23
- };
24
-
25
- const expire: Semantics = async (ctx) => {
26
- const id = at(ctx, 'key');
27
- if (!ctx.get('ephemeral_key', id)) return fail(ctx, `No such ephemeral key: '${id}'`, 404, 'resource_missing');
28
- return ctx.reply(await ctx.write('ephemeral_key', id, { expires: ctx.now() }, 'ephemeral_key.delete'));
29
- };
30
-
31
- export const ephemeralKeys: Record<string, Semantics> = {
32
- PostEphemeralKeys: create,
33
- DeleteEphemeralKeysKey: expire,
34
- };
@@ -1,143 +0,0 @@
1
- // File, file link, Identity and billing-portal semantics. A file is the uploaded document's object
2
- // (the twin keeps no bytes); a file link is answered, not kept. An Identity verification session is
3
- // created here and verified through the twin's own helper outside Stripe's surface; its reports
4
- // are the derived core's to list and read, as are file list and retrieve, session retrieve and
5
- // portal-configuration retrieve.
6
- import type { Semantics, SemanticsContext } from '@volter/world-core';
7
- import { asBool } from '../stripe-twin.ts';
8
- import { actingAccount } from './ledger.ts';
9
- import { at, created, fail, filePurposeRefused, list, mergeUpdate, newest, where, type Row } from './shared.ts';
10
-
11
- /** The type Stripe answers for an uploaded file: "The returned file type (for example, csv, pdf, jpg, or png)"
12
- * (docs.stripe.com/api/files/object). Where the documentation stops and the twin decides: read from the name's
13
- * extension (jpeg as jpg), and null for a name without one. */
14
- function fileType(name: string): string | null {
15
- const ext = /\.([a-z0-9]+)$/i.exec(name)?.[1]?.toLowerCase();
16
- return ext ? (ext === 'jpeg' ? 'jpg' : ext) : null;
17
- }
18
-
19
- // multipart on Stripe; the file is described by the part uploaded: its name, its size in bytes and its type
20
- const createFile: Semantics = async (ctx) => {
21
- const purpose = typeof ctx.params.purpose === 'string' ? ctx.params.purpose : '';
22
- if (!purpose) return fail(ctx, 'Missing required param: purpose.', 400, 'parameter_missing');
23
- const part = ctx.params.file && typeof ctx.params.file === 'object' ? (ctx.params.file as { name?: unknown; type?: unknown; size?: unknown }) : undefined;
24
- const filename = typeof ctx.params.file === 'string' ? ctx.params.file : typeof part?.name === 'string' ? part.name : 'twin_upload';
25
- const made = await created(ctx, 'file', { purpose }, {
26
- filename, size: typeof part?.size === 'number' ? part.size : 0,
27
- type: fileType(filename), title: null, expires_at: null, url: null,
28
- links: { object: 'list', data: [], has_more: false, total_count: 0, url: '' },
29
- });
30
- await syncLinks(ctx, String(made.id));
31
- return ctx.reply(ctx.get('file', String(made.id))!);
32
- };
33
-
34
- /** A file's links, kept in step with the links made to it, at the address Stripe lists them
35
- * (/v1/file_links?file=…, the File object's example). */
36
- async function syncLinks(ctx: SemanticsContext, fileId: string): Promise<void> {
37
- const data = newest(ctx, 'file_link').filter((l) => l.file === fileId);
38
- await ctx.write('file', fileId, { links: { object: 'list', data, has_more: false, url: `/v1/file_links?file=${fileId}` } }, 'file.links_synced');
39
- }
40
-
41
- /** The purposes a file link may be made to: "The file's `purpose` must be one of the following: …" (the served
42
- * spec, POST /v1/file_links `file`). */
43
- const LINKABLE = ['business_icon', 'business_logo', 'customer_signature', 'dispute_evidence', 'finance_report_run', 'financial_account_statement', 'identity_document_downloadable', 'issuing_regulatory_reporting', 'pci_document', 'selfie', 'sigma_scheduled_query', 'tax_document_user_upload', 'terminal_android_apk', 'terminal_reader_splashscreen'] as const;
44
-
45
- // `file` is required; a link is kept, has its own public url, and is listed on its file
46
- const createFileLink: Semantics = async (ctx) => {
47
- if (ctx.params.file === undefined || ctx.params.file === '') return fail(ctx, 'Missing required param: file.', 400, 'parameter_missing');
48
- const fileId = String(ctx.params.file);
49
- const refused = filePurposeRefused(ctx, 'file', LINKABLE);
50
- if (refused) return refused;
51
- const id = ctx.mint('file_link');
52
- const link = await created(ctx, 'file_link', { ...ctx.params, id, file: fileId }, {
53
- url: `https://files.twin.local/links/${id}`, expired: false, livemode: false, metadata: {},
54
- expires_at: ctx.params.expires_at !== undefined ? Number(ctx.params.expires_at) : null,
55
- });
56
- await syncLinks(ctx, fileId);
57
- return ctx.reply(link);
58
- };
59
-
60
- // the person verifies at the session's url, Stripe Identity's hosted page (../screens/identity.tsx)
61
- const createVerificationSession: Semantics = async (ctx) => {
62
- const id = ctx.mint('identity.verification_session');
63
- return ctx.reply(await created(ctx, 'identity.verification_session', { ...ctx.params, id }, {
64
- status: 'requires_input', livemode: false, client_secret: `${id}_secret_twin`, url: `https://verify.stripe.com/start/${id}`,
65
- last_error: null, last_verification_report: null, verified_outputs: null, return_url: ctx.params.return_url ?? null,
66
- }));
67
- };
68
-
69
- // ── the customer portal ──
70
-
71
- // the configuration defaults to the account's default one
72
- const createPortalSession: Semantics = async (ctx) => {
73
- const customer = typeof ctx.params.customer === 'string' ? ctx.params.customer : '';
74
- if (!customer) return fail(ctx, 'Missing required param: customer.', 400, 'parameter_missing');
75
- if (!ctx.row('customer', customer, { withDeleted: true })) return fail(ctx, `No such customer: '${customer}'`, 404, 'resource_missing');
76
- const configuration = typeof ctx.params.configuration === 'string' && ctx.params.configuration
77
- ? ctx.params.configuration
78
- : (ctx.rowsRaw('billing_portal.configuration', { withDeleted: true }).find((c) => c.is_default)?.id ?? 'bpc_twin_default');
79
- const id = ctx.mint('billing_portal.session');
80
- return ctx.reply(
81
- await created(ctx, 'billing_portal.session', {
82
- id, customer, configuration, return_url: ctx.params.return_url ?? null, url: `https://billing.stripe.com/p/session/${id}`,
83
- locale: ctx.params.locale ?? null, on_behalf_of: ctx.params.on_behalf_of ?? null, livemode: false,
84
- // the account the session was made on (Stripe-Account), whose name the portal shows (screens/portal.tsx)
85
- ...(actingAccount(ctx) ? { _brand_account: actingAccount(ctx) } : {}),
86
- }, {}),
87
- );
88
- };
89
-
90
- const PBC = 'billing_portal.configuration';
91
-
92
- /** A portal configuration's features, each filled where the request leaves it: every feature is answered (the served
93
- * spec requires all five), as the create page's example answers a request that sets only customer_update and
94
- * invoice_history: payment_method_update disabled, subscription_cancel disabled at_period_end with proration_behavior
95
- * none and its five default reasons, subscription_update disabled with no allowed updates and proration_behavior none
96
- * (docs.stripe.com/api/customer_portal/configurations/create); trial_update_behavior "Defaults to a value of
97
- * `end_trial` if you don't set it during creation" (the served spec). Where the documentation stops and the twin
98
- * decides: a feature the request leaves out is disabled, and schedule_at_period_end has no conditions. */
99
- const PORTAL_FEATURES: Row = {
100
- customer_update: { allowed_updates: [], enabled: false },
101
- invoice_history: { enabled: false },
102
- payment_method_update: { enabled: false, payment_method_configuration: null },
103
- subscription_cancel: { cancellation_reason: { enabled: false, options: ['too_expensive', 'missing_features', 'switched_service', 'unused', 'other'] }, enabled: false, mode: 'at_period_end', proration_behavior: 'none' },
104
- subscription_update: { default_allowed_updates: [], enabled: false, proration_behavior: 'none', schedule_at_period_end: { conditions: [] }, trial_update_behavior: 'end_trial' },
105
- };
106
- const filled = (base: unknown, given: unknown): unknown => {
107
- if (!given || typeof given !== 'object' || Array.isArray(given) || !base || typeof base !== 'object' || Array.isArray(base)) return given === undefined ? base : given;
108
- const out: Row = { ...(base as Row) };
109
- for (const [k, v] of Object.entries(given as Row)) out[k] = filled((base as Row)[k], v);
110
- return out;
111
- };
112
-
113
- const createPortalConfiguration: Semantics = async (ctx) =>
114
- ctx.reply(
115
- 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) }, {
116
- active: true, is_default: false, livemode: false,
117
- login_page: { enabled: false, url: null },
118
- metadata: {}, default_return_url: ctx.params.default_return_url ?? null,
119
- updated: ctx.now(),
120
- }),
121
- );
122
-
123
- const listPortalConfigurations: Semantics = async (ctx) =>
124
- list(ctx, PBC, where(ctx, newest(ctx, PBC), {
125
- active: (c, v) => asBool(c.active) === asBool(v),
126
- is_default: (c, v) => asBool(c.is_default) === asBool(v),
127
- }));
128
-
129
- const updatePortalConfiguration: Semantics = async (ctx) => {
130
- const id = at(ctx, 'configuration');
131
- if (!ctx.get(PBC, id)) return ctx.notFound(PBC, id);
132
- return ctx.reply(await ctx.write(PBC, id, mergeUpdate(ctx, PBC, id, { ...ctx.params, updated: ctx.now() }), 'billing_portal.configuration.update'));
133
- };
134
-
135
- export const files: Record<string, Semantics> = {
136
- PostFiles: createFile,
137
- PostFileLinks: createFileLink,
138
- PostIdentityVerificationSessions: createVerificationSession,
139
- PostBillingPortalSessions: createPortalSession,
140
- PostBillingPortalConfigurations: createPortalConfiguration,
141
- GetBillingPortalConfigurations: listPortalConfigurations,
142
- PostBillingPortalConfigurationsConfiguration: updatePortalConfiguration,
143
- };