@volter/twin-stripe 2.0.37 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (442) hide show
  1. package/README.md +82 -207
  2. package/dist/generated/pack-facts.json +94 -0
  3. package/dist/spec/SOURCE.md +14 -0
  4. package/dist/spec/fixtures3.json.gz +0 -0
  5. package/dist/spec/openapi.json.gz +0 -0
  6. package/dist/spec/patches.json +34 -0
  7. package/dist/spec/sources.json +378 -0
  8. package/dist/src/cli.js +12 -30
  9. package/dist/src/engine/after-payment.d.ts +9 -0
  10. package/dist/src/engine/after-payment.js +28 -0
  11. package/dist/src/engine/apps-secrets.d.ts +1 -0
  12. package/dist/src/engine/apps-secrets.js +3 -0
  13. package/dist/src/engine/balance.d.ts +5 -0
  14. package/dist/src/engine/balance.js +15 -0
  15. package/dist/src/engine/billing.d.ts +5 -0
  16. package/dist/src/engine/billing.js +6 -0
  17. package/dist/src/engine/charges.d.ts +6 -0
  18. package/dist/src/engine/charges.js +13 -0
  19. package/dist/src/engine/checkout.d.ts +24 -0
  20. package/dist/src/engine/checkout.js +30 -0
  21. package/dist/src/engine/common.d.ts +19 -0
  22. package/dist/src/engine/common.js +32 -0
  23. package/dist/src/{screens → engine}/connect-settings.d.ts +1 -7
  24. package/dist/src/engine/connect-settings.js +26 -0
  25. package/dist/src/engine/connect.d.ts +66 -0
  26. package/dist/src/engine/connect.js +189 -0
  27. package/dist/src/engine/coupons.d.ts +0 -0
  28. package/dist/src/engine/coupons.js +5 -0
  29. package/dist/src/engine/credit-notes.d.ts +1 -0
  30. package/dist/src/engine/credit-notes.js +5 -0
  31. package/dist/src/engine/customers.d.ts +12 -0
  32. package/dist/src/engine/customers.js +30 -0
  33. package/dist/src/engine/display.d.ts +14 -0
  34. package/dist/src/engine/display.js +16 -0
  35. package/dist/src/engine/disputes.d.ts +0 -0
  36. package/dist/src/engine/disputes.js +9 -0
  37. package/dist/src/engine/entitlements.d.ts +1 -0
  38. package/dist/src/engine/entitlements.js +4 -0
  39. package/dist/src/engine/ephemeral-keys.d.ts +0 -0
  40. package/dist/src/engine/ephemeral-keys.js +4 -0
  41. package/dist/src/engine/files.d.ts +18 -0
  42. package/dist/src/engine/files.js +33 -0
  43. package/dist/src/engine/front.d.ts +5 -0
  44. package/dist/src/engine/front.js +25 -0
  45. package/dist/src/engine/invoices.d.ts +24 -0
  46. package/dist/src/engine/invoices.js +57 -0
  47. package/dist/src/engine/issuing.d.ts +35 -0
  48. package/dist/src/engine/issuing.js +45 -0
  49. package/dist/src/engine/ledger.d.ts +9 -0
  50. package/dist/src/engine/ledger.js +9 -0
  51. package/dist/src/engine/oauth.d.ts +4 -0
  52. package/dist/src/engine/oauth.js +25 -0
  53. package/dist/src/engine/onboarding.d.ts +13 -0
  54. package/dist/src/engine/onboarding.js +42 -0
  55. package/dist/src/{stripe-params.d.ts → engine/params.d.ts} +20 -3
  56. package/dist/src/{stripe-params.js → engine/params.js} +7 -60
  57. package/dist/src/engine/payment-intents.d.ts +10 -0
  58. package/dist/src/engine/payment-intents.js +27 -0
  59. package/dist/src/engine/payment-links.d.ts +1 -0
  60. package/dist/src/engine/payment-links.js +5 -0
  61. package/dist/src/engine/payment-methods.d.ts +16 -0
  62. package/dist/src/engine/payment-methods.js +22 -0
  63. package/dist/src/engine/plans.d.ts +6 -0
  64. package/dist/src/engine/plans.js +26 -0
  65. package/dist/src/engine/platform.d.ts +39 -0
  66. package/dist/src/engine/platform.js +34 -0
  67. package/dist/src/engine/products.d.ts +0 -0
  68. package/dist/src/engine/products.js +4 -0
  69. package/dist/src/engine/radar.d.ts +2 -0
  70. package/dist/src/engine/radar.js +5 -0
  71. package/dist/src/engine/refunds.d.ts +1 -0
  72. package/dist/src/engine/refunds.js +28 -0
  73. package/dist/src/engine/renewals.d.ts +36 -0
  74. package/dist/src/engine/renewals.js +65 -0
  75. package/dist/src/engine/setup-intents.d.ts +1 -0
  76. package/dist/src/engine/setup-intents.js +4 -0
  77. package/dist/src/{stripe-twin.d.ts → engine/stripe.d.ts} +11 -39
  78. package/dist/src/{stripe-twin.js → engine/stripe.js} +25 -310
  79. package/dist/src/engine/subscription-schedules.d.ts +3 -0
  80. package/dist/src/engine/subscription-schedules.js +1 -0
  81. package/dist/src/engine/subscriptions.d.ts +12 -0
  82. package/dist/src/engine/subscriptions.js +31 -0
  83. package/dist/src/engine/tax.d.ts +7 -0
  84. package/dist/src/engine/tax.js +28 -0
  85. package/dist/src/engine/terminal.d.ts +4 -0
  86. package/dist/src/engine/terminal.js +20 -0
  87. package/dist/src/engine/test-clocks.d.ts +5 -0
  88. package/dist/src/engine/test-clocks.js +9 -0
  89. package/dist/src/engine/tokens.d.ts +7 -0
  90. package/dist/src/engine/tokens.js +20 -0
  91. package/dist/src/engine/transfers.d.ts +2 -0
  92. package/dist/src/engine/transfers.js +1 -0
  93. package/dist/src/engine/treasury.d.ts +23 -0
  94. package/dist/src/engine/treasury.js +45 -0
  95. package/dist/src/{stripe-version.js → engine/version.js} +4 -3
  96. package/dist/src/engine/webhook-endpoints.d.ts +1 -0
  97. package/dist/src/engine/webhook-endpoints.js +12 -0
  98. package/dist/src/engine/webhooks.d.ts +31 -0
  99. package/dist/src/engine/webhooks.js +68 -0
  100. package/dist/src/fetch.d.ts +2 -0
  101. package/dist/src/fetch.js +26 -0
  102. package/dist/src/generated/surface.gen.json +1 -1
  103. package/dist/src/generated/ui.gen.json +1 -1
  104. package/dist/src/index.d.ts +5 -14
  105. package/dist/src/index.js +8 -75
  106. package/dist/src/manifest.js +232 -758
  107. package/dist/src/screens/billing-portal.d.ts +3 -0
  108. package/dist/src/screens/{portal.js → billing-portal.js} +28 -54
  109. package/dist/src/screens/checkout.d.ts +2 -31
  110. package/dist/src/screens/checkout.js +32 -121
  111. package/dist/src/screens/connect-oauth.d.ts +3 -27
  112. package/dist/src/screens/connect-oauth.js +51 -132
  113. package/dist/src/screens/connect-onboarding.d.ts +3 -0
  114. package/dist/src/screens/{onboarding.js → connect-onboarding.js} +36 -102
  115. package/dist/src/screens/dashboard.d.ts +3 -0
  116. package/dist/src/screens/dashboard.js +117 -0
  117. package/dist/src/screens/shared.d.ts +27 -0
  118. package/dist/src/screens/shared.js +87 -0
  119. package/dist/src/screens/stripe-js.d.ts +3 -0
  120. package/dist/src/screens/stripe-js.js +135 -0
  121. package/dist/src/semantics/account_links.d.ts +2 -0
  122. package/dist/src/semantics/account_links.js +22 -0
  123. package/dist/src/semantics/accounts.d.ts +4 -0
  124. package/dist/src/semantics/accounts.js +38 -0
  125. package/dist/src/semantics/apps.d.ts +4 -0
  126. package/dist/src/semantics/{apps-secrets.js → apps.js} +14 -26
  127. package/dist/src/semantics/around.d.ts +2 -0
  128. package/dist/src/semantics/around.js +16 -0
  129. package/dist/src/semantics/balance.d.ts +2 -11
  130. package/dist/src/semantics/balance.js +3 -194
  131. package/dist/src/semantics/balance_transactions.d.ts +2 -0
  132. package/dist/src/semantics/balance_transactions.js +15 -0
  133. package/dist/src/semantics/billing_portal.d.ts +5 -0
  134. package/dist/src/semantics/billing_portal.js +42 -0
  135. package/dist/src/semantics/charges.d.ts +3 -28
  136. package/dist/src/semantics/charges.js +5 -202
  137. package/dist/src/semantics/checkout.d.ts +3 -20
  138. package/dist/src/semantics/checkout.js +8 -261
  139. package/dist/src/semantics/clock.d.ts +2 -0
  140. package/dist/src/semantics/clock.js +21 -0
  141. package/dist/src/semantics/coupons.d.ts +2 -6
  142. package/dist/src/semantics/coupons.js +2 -60
  143. package/dist/src/semantics/customers.d.ts +6 -6
  144. package/dist/src/semantics/customers.js +27 -387
  145. package/dist/src/semantics/disputes.d.ts +2 -2
  146. package/dist/src/semantics/disputes.js +3 -49
  147. package/dist/src/semantics/doors.d.ts +23 -0
  148. package/dist/src/semantics/doors.js +73 -0
  149. package/dist/src/semantics/entitlements.d.ts +2 -2
  150. package/dist/src/semantics/entitlements.js +5 -50
  151. package/dist/src/semantics/events.d.ts +12 -0
  152. package/dist/src/semantics/events.js +36 -0
  153. package/dist/src/semantics/index.d.ts +2 -0
  154. package/dist/src/semantics/index.js +107 -0
  155. package/dist/src/semantics/invoice_payments.d.ts +2 -0
  156. package/dist/src/semantics/invoice_payments.js +12 -0
  157. package/dist/src/semantics/invoiceitems.d.ts +3 -0
  158. package/dist/src/semantics/invoiceitems.js +59 -0
  159. package/dist/src/semantics/invoices.d.ts +16 -18
  160. package/dist/src/semantics/invoices.js +118 -444
  161. package/dist/src/semantics/payment_intents.d.ts +4 -0
  162. package/dist/src/semantics/payment_intents.js +79 -0
  163. package/dist/src/semantics/payment_methods.d.ts +5 -0
  164. package/dist/src/semantics/payment_methods.js +39 -0
  165. package/dist/src/semantics/payouts.d.ts +2 -0
  166. package/dist/src/semantics/payouts.js +21 -0
  167. package/dist/src/semantics/prices.d.ts +4 -0
  168. package/dist/src/semantics/prices.js +37 -0
  169. package/dist/src/semantics/products.d.ts +6 -2
  170. package/dist/src/semantics/products.js +15 -130
  171. package/dist/src/semantics/promotion_codes.d.ts +3 -0
  172. package/dist/src/semantics/promotion_codes.js +35 -0
  173. package/dist/src/semantics/radar.d.ts +2 -2
  174. package/dist/src/semantics/radar.js +5 -74
  175. package/dist/src/semantics/refunds.d.ts +3 -9
  176. package/dist/src/semantics/refunds.js +6 -192
  177. package/dist/src/semantics/setup_intents.d.ts +3 -0
  178. package/dist/src/semantics/{setup-intents.js → setup_intents.js} +10 -53
  179. package/dist/src/semantics/shared.d.ts +822 -47
  180. package/dist/src/semantics/shared.js +3044 -78
  181. package/dist/src/semantics/states.d.ts +531 -0
  182. package/dist/src/semantics/states.js +852 -0
  183. package/dist/src/semantics/subscription_items.d.ts +5 -0
  184. package/dist/src/semantics/subscription_items.js +55 -0
  185. package/dist/src/semantics/subscription_schedules.d.ts +4 -0
  186. package/dist/src/semantics/subscription_schedules.js +60 -0
  187. package/dist/src/semantics/subscriptions.d.ts +7 -11
  188. package/dist/src/semantics/subscriptions.js +44 -415
  189. package/dist/src/semantics/test_helpers.d.ts +6 -0
  190. package/dist/src/semantics/{test-clocks.js → test_helpers.js} +14 -40
  191. package/dist/src/semantics/transfers.d.ts +2 -2
  192. package/dist/src/semantics/transfers.js +6 -101
  193. package/dist/src/server.d.ts +7 -0
  194. package/dist/src/server.js +7 -0
  195. package/generated/pack-facts.json +94 -0
  196. package/package.json +10 -20
  197. package/spec/SOURCE.md +14 -0
  198. package/spec/fixtures3.json.gz +0 -0
  199. package/spec/openapi.json.gz +0 -0
  200. package/spec/patches.json +34 -0
  201. package/spec/sources.json +378 -0
  202. package/src/cli.ts +12 -26
  203. package/src/engine/after-payment.ts +31 -0
  204. package/src/engine/apps-secrets.ts +4 -0
  205. package/src/engine/balance.ts +33 -0
  206. package/src/engine/billing.ts +16 -0
  207. package/src/engine/charges.ts +19 -0
  208. package/src/engine/checkout.ts +40 -0
  209. package/src/engine/common.ts +47 -0
  210. package/src/engine/connect-settings.ts +23 -0
  211. package/src/engine/connect.ts +184 -0
  212. package/src/engine/coupons.ts +5 -0
  213. package/src/engine/credit-notes.ts +6 -0
  214. package/src/engine/customers.ts +35 -0
  215. package/src/engine/display.ts +19 -0
  216. package/src/engine/disputes.ts +9 -0
  217. package/src/engine/entitlements.ts +5 -0
  218. package/src/engine/ephemeral-keys.ts +3 -0
  219. package/src/engine/files.ts +41 -0
  220. package/src/engine/front.ts +31 -0
  221. package/src/engine/invoices.ts +71 -0
  222. package/src/engine/issuing.ts +61 -0
  223. package/src/engine/ledger.ts +50 -0
  224. package/src/engine/oauth.ts +19 -0
  225. package/src/engine/onboarding.ts +54 -0
  226. package/src/{stripe-params.ts → engine/params.ts} +8 -56
  227. package/src/engine/payment-intents.ts +33 -0
  228. package/src/engine/payment-links.ts +6 -0
  229. package/src/engine/payment-methods.ts +25 -0
  230. package/src/engine/plans.ts +42 -0
  231. package/src/engine/platform.ts +47 -0
  232. package/src/engine/products.ts +3 -0
  233. package/src/engine/radar.ts +6 -0
  234. package/src/engine/refunds.ts +29 -0
  235. package/src/engine/renewals.ts +73 -0
  236. package/src/engine/setup-intents.ts +5 -0
  237. package/src/{stripe-twin.ts → engine/stripe.ts} +28 -323
  238. package/src/engine/subscription-schedules.ts +10 -0
  239. package/src/engine/subscriptions.ts +40 -0
  240. package/src/engine/tax.ts +39 -0
  241. package/src/engine/terminal.ts +23 -0
  242. package/src/engine/test-clocks.ts +11 -0
  243. package/src/engine/tokens.ts +22 -0
  244. package/src/engine/transfers.ts +23 -0
  245. package/src/engine/treasury.ts +47 -0
  246. package/src/{stripe-version.ts → engine/version.ts} +4 -3
  247. package/src/engine/webhook-endpoints.ts +14 -0
  248. package/src/engine/webhooks.ts +72 -0
  249. package/src/fetch.ts +27 -0
  250. package/src/generated/surface.gen.json +1 -1
  251. package/src/generated/ui.gen.json +1 -1
  252. package/src/index.ts +8 -116
  253. package/src/manifest.ts +234 -786
  254. package/src/screens/{portal.tsx → billing-portal.tsx} +32 -37
  255. package/src/screens/checkout.tsx +33 -95
  256. package/src/screens/connect-oauth.tsx +64 -88
  257. package/src/screens/{onboarding.tsx → connect-onboarding.tsx} +38 -82
  258. package/src/screens/dashboard.tsx +198 -0
  259. package/src/screens/shared.tsx +84 -0
  260. package/src/screens/stripe-js.ts +170 -0
  261. package/src/semantics/account_links.ts +21 -0
  262. package/src/semantics/accounts.ts +43 -0
  263. package/src/semantics/{apps-secrets.ts → apps.ts} +17 -32
  264. package/src/semantics/around.ts +20 -0
  265. package/src/semantics/balance.ts +6 -207
  266. package/src/semantics/balance_transactions.ts +20 -0
  267. package/src/semantics/billing_portal.ts +51 -0
  268. package/src/semantics/charges.ts +12 -211
  269. package/src/semantics/checkout.ts +13 -268
  270. package/src/semantics/clock.ts +26 -0
  271. package/src/semantics/coupons.ts +5 -67
  272. package/src/semantics/customers.ts +29 -392
  273. package/src/semantics/disputes.ts +9 -59
  274. package/src/semantics/doors.ts +80 -0
  275. package/src/semantics/entitlements.ts +9 -56
  276. package/src/semantics/events.ts +44 -0
  277. package/src/semantics/index.ts +111 -0
  278. package/src/semantics/invoice_payments.ts +18 -0
  279. package/src/semantics/invoiceitems.ts +59 -0
  280. package/src/semantics/invoices.ts +109 -443
  281. package/src/semantics/payment_intents.ts +83 -0
  282. package/src/semantics/payment_methods.ts +43 -0
  283. package/src/semantics/payouts.ts +23 -0
  284. package/src/semantics/prices.ts +42 -0
  285. package/src/semantics/products.ts +18 -142
  286. package/src/semantics/promotion_codes.ts +39 -0
  287. package/src/semantics/radar.ts +8 -77
  288. package/src/semantics/refunds.ts +9 -212
  289. package/src/semantics/setup_intents.ts +45 -0
  290. package/src/semantics/shared.ts +3092 -106
  291. package/src/semantics/states.ts +883 -0
  292. package/src/semantics/subscription_items.ts +54 -0
  293. package/src/semantics/subscription_schedules.ts +66 -0
  294. package/src/semantics/subscriptions.ts +49 -432
  295. package/src/semantics/{test-clocks.ts → test_helpers.ts} +23 -47
  296. package/src/semantics/transfers.ts +11 -131
  297. package/src/server.ts +8 -0
  298. package/client/dashboard-api.ts +0 -286
  299. package/client/stripe-mirror.css +0 -277
  300. package/client/stripe-mirror.tsx +0 -1559
  301. package/dist/client/dashboard-api.d.ts +0 -107
  302. package/dist/client/dashboard-api.js +0 -238
  303. package/dist/client/dashboard-api.ts +0 -286
  304. package/dist/client/stripe-mirror.bundle.js +0 -236
  305. package/dist/client/stripe-mirror.css +0 -277
  306. package/dist/client/stripe-mirror.d.ts +0 -134
  307. package/dist/client/stripe-mirror.js +0 -859
  308. package/dist/client/stripe-mirror.tsx +0 -1559
  309. package/dist/src/screens/connect-settings.js +0 -103
  310. package/dist/src/screens/consent-skin.d.ts +0 -4
  311. package/dist/src/screens/consent-skin.js +0 -18
  312. package/dist/src/screens/financial-connections.d.ts +0 -5
  313. package/dist/src/screens/financial-connections.js +0 -90
  314. package/dist/src/screens/identity.d.ts +0 -5
  315. package/dist/src/screens/identity.js +0 -86
  316. package/dist/src/screens/onboarding.d.ts +0 -13
  317. package/dist/src/screens/portal.d.ts +0 -5
  318. package/dist/src/screens/public-details.d.ts +0 -5
  319. package/dist/src/screens/public-details.js +0 -90
  320. package/dist/src/semantics/after-payment.d.ts +0 -22
  321. package/dist/src/semantics/after-payment.js +0 -99
  322. package/dist/src/semantics/apps-secrets.d.ts +0 -2
  323. package/dist/src/semantics/billing.d.ts +0 -2
  324. package/dist/src/semantics/billing.js +0 -220
  325. package/dist/src/semantics/connect.d.ts +0 -5
  326. package/dist/src/semantics/connect.js +0 -493
  327. package/dist/src/semantics/credit-notes.d.ts +0 -2
  328. package/dist/src/semantics/credit-notes.js +0 -172
  329. package/dist/src/semantics/ephemeral-keys.d.ts +0 -2
  330. package/dist/src/semantics/ephemeral-keys.js +0 -34
  331. package/dist/src/semantics/files.d.ts +0 -2
  332. package/dist/src/semantics/files.js +0 -125
  333. package/dist/src/semantics/issuing.d.ts +0 -13
  334. package/dist/src/semantics/issuing.js +0 -575
  335. package/dist/src/semantics/ledger.d.ts +0 -59
  336. package/dist/src/semantics/ledger.js +0 -200
  337. package/dist/src/semantics/payment-intents.d.ts +0 -18
  338. package/dist/src/semantics/payment-intents.js +0 -452
  339. package/dist/src/semantics/payment-links.d.ts +0 -2
  340. package/dist/src/semantics/payment-links.js +0 -133
  341. package/dist/src/semantics/payment-methods.d.ts +0 -20
  342. package/dist/src/semantics/payment-methods.js +0 -140
  343. package/dist/src/semantics/plans.d.ts +0 -5
  344. package/dist/src/semantics/plans.js +0 -121
  345. package/dist/src/semantics/platform.d.ts +0 -9
  346. package/dist/src/semantics/platform.js +0 -206
  347. package/dist/src/semantics/renewals.d.ts +0 -47
  348. package/dist/src/semantics/renewals.js +0 -281
  349. package/dist/src/semantics/setup-intents.d.ts +0 -2
  350. package/dist/src/semantics/subscription-schedules.d.ts +0 -2
  351. package/dist/src/semantics/subscription-schedules.js +0 -119
  352. package/dist/src/semantics/tax.d.ts +0 -2
  353. package/dist/src/semantics/tax.js +0 -197
  354. package/dist/src/semantics/terminal.d.ts +0 -5
  355. package/dist/src/semantics/terminal.js +0 -182
  356. package/dist/src/semantics/test-clocks.d.ts +0 -6
  357. package/dist/src/semantics/tokens.d.ts +0 -4
  358. package/dist/src/semantics/tokens.js +0 -44
  359. package/dist/src/semantics/treasury.d.ts +0 -2
  360. package/dist/src/semantics/treasury.js +0 -377
  361. package/dist/src/semantics/webhook-endpoints.d.ts +0 -3
  362. package/dist/src/semantics/webhook-endpoints.js +0 -85
  363. package/dist/src/stripe-budget.d.ts +0 -55
  364. package/dist/src/stripe-budget.js +0 -155
  365. package/dist/src/stripe-capabilities.d.ts +0 -3
  366. package/dist/src/stripe-capabilities.js +0 -5836
  367. package/dist/src/stripe-conformance.d.ts +0 -43
  368. package/dist/src/stripe-conformance.js +0 -105
  369. package/dist/src/stripe-connector.d.ts +0 -161
  370. package/dist/src/stripe-connector.js +0 -414
  371. package/dist/src/stripe-emit.d.ts +0 -2
  372. package/dist/src/stripe-emit.js +0 -145
  373. package/dist/src/stripe-events.d.ts +0 -93
  374. package/dist/src/stripe-events.js +0 -392
  375. package/dist/src/stripe-js.d.ts +0 -4
  376. package/dist/src/stripe-js.js +0 -70
  377. package/dist/src/stripe-mirror-ui.d.ts +0 -15
  378. package/dist/src/stripe-mirror-ui.js +0 -87
  379. package/dist/src/stripe-perform-harness.d.ts +0 -9
  380. package/dist/src/stripe-perform-harness.js +0 -26
  381. package/dist/src/stripe-server.d.ts +0 -33
  382. package/dist/src/stripe-server.js +0 -429
  383. package/dist/src/stripe-shared.d.ts +0 -109
  384. package/dist/src/stripe-shared.js +0 -276
  385. package/dist/src/stripe-ui-conformance.d.ts +0 -5
  386. package/dist/src/stripe-ui-conformance.js +0 -79
  387. package/dist/src/stripe-ui-structure.d.ts +0 -3
  388. package/dist/src/stripe-ui-structure.js +0 -168
  389. package/dist/test-fixtures/stripe-known-deviations.json +0 -110
  390. package/dist/test-fixtures/stripe-openapi-operations.SOURCE.md +0 -14
  391. package/dist/test-fixtures/stripe-openapi-operations.json +0 -4717
  392. package/dist/test-fixtures/stripe-schemas.SOURCE.md +0 -35
  393. package/dist/test-fixtures/stripe-schemas.json +0 -3813
  394. package/src/screens/connect-settings.tsx +0 -121
  395. package/src/screens/consent-skin.ts +0 -20
  396. package/src/screens/financial-connections.tsx +0 -101
  397. package/src/screens/identity.tsx +0 -96
  398. package/src/screens/public-details.tsx +0 -105
  399. package/src/semantics/after-payment.ts +0 -118
  400. package/src/semantics/billing.ts +0 -216
  401. package/src/semantics/connect.ts +0 -487
  402. package/src/semantics/credit-notes.ts +0 -168
  403. package/src/semantics/ephemeral-keys.ts +0 -34
  404. package/src/semantics/files.ts +0 -143
  405. package/src/semantics/issuing.ts +0 -590
  406. package/src/semantics/ledger.ts +0 -253
  407. package/src/semantics/payment-intents.ts +0 -463
  408. package/src/semantics/payment-links.ts +0 -148
  409. package/src/semantics/payment-methods.ts +0 -145
  410. package/src/semantics/plans.ts +0 -131
  411. package/src/semantics/platform.ts +0 -220
  412. package/src/semantics/renewals.ts +0 -279
  413. package/src/semantics/setup-intents.ts +0 -87
  414. package/src/semantics/subscription-schedules.ts +0 -129
  415. package/src/semantics/tax.ts +0 -220
  416. package/src/semantics/terminal.ts +0 -195
  417. package/src/semantics/tokens.ts +0 -52
  418. package/src/semantics/treasury.ts +0 -383
  419. package/src/semantics/webhook-endpoints.ts +0 -87
  420. package/src/stripe-budget.ts +0 -181
  421. package/src/stripe-capabilities.ts +0 -5651
  422. package/src/stripe-conformance.ts +0 -124
  423. package/src/stripe-connector.ts +0 -462
  424. package/src/stripe-emit.ts +0 -157
  425. package/src/stripe-events.ts +0 -434
  426. package/src/stripe-js.ts +0 -70
  427. package/src/stripe-mirror-ui.ts +0 -90
  428. package/src/stripe-perform-harness.ts +0 -29
  429. package/src/stripe-server.ts +0 -393
  430. package/src/stripe-shared.ts +0 -297
  431. package/src/stripe-ui-conformance.ts +0 -88
  432. package/src/stripe-ui-structure.ts +0 -182
  433. package/test-fixtures/stripe-known-deviations.json +0 -110
  434. package/test-fixtures/stripe-openapi-operations.json +0 -4717
  435. package/test-fixtures/stripe-schemas.json +0 -3813
  436. /package/dist/src/{screens → engine}/industries.d.ts +0 -0
  437. /package/dist/src/{screens → engine}/industries.js +0 -0
  438. /package/dist/src/{semantics → engine}/test-cards.d.ts +0 -0
  439. /package/dist/src/{semantics → engine}/test-cards.js +0 -0
  440. /package/dist/src/{stripe-version.d.ts → engine/version.d.ts} +0 -0
  441. /package/src/{screens → engine}/industries.ts +0 -0
  442. /package/src/{semantics → engine}/test-cards.ts +0 -0
@@ -1,145 +0,0 @@
1
- // PaymentMethod semantics: a PaymentMethod is created detached, attached to a customer, and
2
- // detached again. The list is the derived core's.
3
- import type { Semantics, SemanticsContext } from '@volter/world-core';
4
- import { declineFor, paymentMethodSubObject, TEST_TOKEN_DECLINES } from '../stripe-twin.ts';
5
- import { AFTER_SUCCESS_CARDS, afterSuccessOf } from './after-payment.ts';
6
- import { at, created, fail, type Row } from './shared.ts';
7
-
8
- const PM = 'payment_method';
9
- const noBilling = { address: null, email: null, name: null, phone: null };
10
- const pmMissing = (ctx: SemanticsContext, id: string): Response => fail(ctx, `No such payment_method: '${id}'`, 404, 'resource_missing');
11
-
12
- // the raw card number, cvc and bank account number are never echoed: the modeled sub-object is
13
- // what the PaymentMethod carries, with the decline outcome its card implies, so a later charge
14
- // naming it only by id declines the same way
15
- const create: Semantics = async (ctx) => {
16
- const params = ctx.params;
17
- const pmType = typeof params.type === 'string' ? params.type : 'card';
18
- const { card: _card, sepa_debit: _sepa, us_bank_account: _ach, type: _t, ...rest } = params;
19
- const sub = paymentMethodSubObject(pmType, params);
20
- const declineOutcome = pmType === 'card' ? (declineFor(() => undefined, params) ?? null) : null;
21
- // and what Stripe does after its card succeeds (a dispute, a review), which a later charge naming it by id brings
22
- const afterSuccess = pmType === 'card' ? afterSuccessOf(ctx, params.card) : undefined;
23
- // the billing details the create gives are the method's (docs.stripe.com/api/payment_methods/create#create_payment_method-billing_details)
24
- const given = rest.billing_details && typeof rest.billing_details === 'object' ? (rest.billing_details as Row) : {};
25
- return ctx.reply(await created(ctx, PM, { ...rest, type: pmType, customer: null, livemode: false, billing_details: { ...noBilling, ...given }, ...sub, _declineOutcome: declineOutcome, ...(afterSuccess ? { _afterSuccess: afterSuccess } : {}) }, {}));
26
- };
27
-
28
- const TEST_PM_CARDS: Record<string, { brand: string; number: string }> = {
29
- ...AFTER_SUCCESS_CARDS,
30
- pm_card_mastercard: { brand: 'mastercard', number: '5555555555554444' },
31
- pm_card_amex: { brand: 'amex', number: '378282246310005' },
32
- pm_card_discover: { brand: 'discover', number: '6011111111111117' },
33
- };
34
-
35
- /** The card a charge was paid with, as its payment_method_details reports it
36
- * (docs.stripe.com/api/charges/object#charge_object-payment_method_details): a stored PaymentMethod's card, a
37
- * documented test name (pm_card_* or tok_*, the same cards), or a raw card; undefined for anything else. */
38
- export function paymentMethodDetails(ctx: SemanticsContext, ref: unknown): Row | undefined {
39
- let card: Row | undefined;
40
- // a payment method of another kind (a US bank account) is described by its own block, as the charge reports it
41
- const stored = typeof ref === 'string' && ref ? ctx.get(PM, ref) : undefined;
42
- // Stripe's US bank account test methods (pm_us_bank_account, pm_usBankAccount_*) are its test bank's account
43
- const pm = stored ?? (typeof ref === 'string' && /^pm_us_?bank_?account/i.test(ref) ? { type: 'us_bank_account', ...paymentMethodSubObject('us_bank_account', {}) } : undefined);
44
- if (pm && typeof pm.type === 'string' && pm.type !== 'card') {
45
- const own = (pm[pm.type] as Row | undefined) ?? {};
46
- const pick = ['account_holder_type', 'account_type', 'bank_name', 'fingerprint', 'last4', 'routing_number'];
47
- return { type: pm.type, [pm.type]: Object.fromEntries(pick.filter((k) => own[k] !== undefined).map((k) => [k, own[k]])) };
48
- }
49
- if (typeof ref === 'string' && ref) {
50
- const stored = ctx.get(PM, ref)?.card as Row | undefined;
51
- if (stored) card = stored;
52
- else card = testCardOf(ref);
53
- } else if (ref && typeof ref === 'object') card = paymentMethodSubObject('card', { card: ref }).card as Row;
54
- if (!card) return undefined;
55
- return {
56
- type: 'card',
57
- card: {
58
- brand: card.brand, last4: card.last4, exp_month: card.exp_month, exp_year: card.exp_year, funding: card.funding ?? 'credit',
59
- country: card.country ?? 'US', network: card.brand, fingerprint: card.fingerprint ?? null,
60
- checks: card.checks ?? { address_line1_check: null, address_postal_code_check: null, cvc_check: 'pass' },
61
- three_d_secure: null, wallet: null, installments: null, mandate: null,
62
- },
63
- };
64
- }
65
-
66
- // attaching needs an existing customer; a well-known test token (pm_card_visa, …) is a template:
67
- // attaching it mints a new PaymentMethod on the customer carrying that card's outcome
68
- /** Whether a payment method can be attached: a stored one, or a documented test name that attaching mints. */
69
- export const attachable = (ctx: SemanticsContext, id: string): boolean => !!ctx.get(PM, id) || (id.startsWith('pm_card_') && (id in TEST_TOKEN_DECLINES || id in AFTER_SUCCESS_CARDS));
70
-
71
- /** Attach a payment method to a customer (both known to exist or be attachable): a stored one moves to the
72
- * customer; a test name mints a new PaymentMethod on the customer carrying that card's outcome. */
73
- /** The card a test name (pm_card_*, tok_*) stands for, never stored as a PaymentMethod (docs.stripe.com/testing#cards). */
74
- function testCardOf(ref: string): Row | undefined {
75
- const name = ref.replace(/^tok_/, 'pm_card_');
76
- if (!name.startsWith('pm_card_')) return undefined;
77
- const test = TEST_PM_CARDS[name] ?? { brand: 'visa', number: '4242424242424242' };
78
- return { ...(paymentMethodSubObject('card', { card: { number: test.number } }).card as Row), brand: test.brand };
79
- }
80
-
81
- export async function attachPaymentMethod(ctx: SemanticsContext, id: string, customer: string): Promise<Row> {
82
- if (!ctx.get(PM, id)) return materializeTestMethod(ctx, id, customer);
83
- return ctx.write(PM, id, { customer }, 'payment_method.attach');
84
- }
85
-
86
- /** A documented test name (pm_card_visa, pm_card_visa_chargeDeclined, …) made a real PaymentMethod, as Stripe
87
- * does when one is used: the brand and number it stands for (docs.stripe.com/testing#cards) and its outcome. */
88
- export async function materializeTestMethod(ctx: SemanticsContext, id: string, customer: string | null): Promise<Row> {
89
- const card = TEST_PM_CARDS[id] ?? { brand: 'visa', number: '4242424242424242' };
90
- const sub = paymentMethodSubObject('card', { card: { number: card.number } });
91
- (sub.card as Record<string, unknown>).brand = card.brand;
92
- const afterSuccess = AFTER_SUCCESS_CARDS[id]?.outcome;
93
- return created(ctx, PM, { type: 'card', customer, livemode: false, billing_details: noBilling, ...sub, _declineOutcome: TEST_TOKEN_DECLINES[id] ?? null, ...(afterSuccess ? { _afterSuccess: afterSuccess } : {}) }, {});
94
- }
95
-
96
- const attach: Semantics = async (ctx) => {
97
- const id = at(ctx, 'payment_method');
98
- const customer = typeof ctx.params.customer === 'string' ? ctx.params.customer : '';
99
- if (!customer) return fail(ctx, 'Missing required param: customer.', 400, 'parameter_missing');
100
- if (!ctx.get('customer', customer)) return fail(ctx, `No such customer: '${customer}'`, 400, 'resource_missing');
101
- if (!attachable(ctx, id)) return pmMissing(ctx, id);
102
- return ctx.reply(await attachPaymentMethod(ctx, id, customer));
103
- };
104
-
105
- const retrieve: Semantics = async (ctx) => {
106
- const m = ctx.get(PM, at(ctx, 'payment_method'));
107
- return m ? ctx.reply(m) : pmMissing(ctx, at(ctx, 'payment_method'));
108
- };
109
-
110
- const detach: Semantics = async (ctx) => {
111
- const id = at(ctx, 'payment_method');
112
- if (!ctx.get(PM, id)) return pmMissing(ctx, id);
113
- return ctx.reply(await ctx.write(PM, id, { customer: null }, 'payment_method.detach'));
114
- };
115
-
116
- export const paymentMethods: Record<string, Semantics> = {
117
- PostPaymentMethods: create,
118
- PostPaymentMethodsPaymentMethodAttach: attach,
119
- GetPaymentMethodsPaymentMethod: retrieve,
120
- PostPaymentMethodsPaymentMethodDetach: detach,
121
- };
122
-
123
- /** A PaymentMethod made from a confirm's `payment_method_data` ("If provided, this hash will be used to create a
124
- * PaymentMethod", docs.stripe.com/api/setup_intents/confirm, docs.stripe.com/api/payment_intents/confirm), or none. */
125
- export async function methodFromData(ctx: SemanticsContext, data: unknown): Promise<string | undefined> {
126
- if (!data || typeof data !== 'object') return undefined;
127
- const d = data as Row;
128
- const type = typeof d.type === 'string' ? d.type : 'card';
129
- const made = await created(ctx, PM, {}, {
130
- type, customer: null, livemode: false, metadata: {},
131
- billing_details: { ...noBilling, ...((d.billing_details as Row | undefined) ?? {}) },
132
- ...paymentMethodSubObject(type, d),
133
- // what follows its card's success (a dispute, funds straight to available), as a PaymentMethod created directly carries
134
- ...(type === 'card' && afterSuccessOf(ctx, d.card) ? { _afterSuccess: afterSuccessOf(ctx, d.card) } : {}),
135
- });
136
- return String(made.id);
137
- }
138
-
139
- /** Whether an intent sets up or pays with a bank account by micro-deposits because it asks for them:
140
- * payment_method_options[us_bank_account][verification_method]=microdeposits with a us_bank_account method
141
- * ("Microdeposit only verification", docs.stripe.com/payments/ach-direct-debit/set-up-payment). */
142
- export function microdepositsAsked(ctx: SemanticsContext, params: Row, intent: Row, pm: string | undefined): boolean {
143
- const options = ((params.payment_method_options ?? intent.payment_method_options) as Row | undefined)?.us_bank_account as Row | undefined;
144
- return options?.verification_method === 'microdeposits' && !!pm && ctx.get(PM, pm)?.type === 'us_bank_account';
145
- }
@@ -1,131 +0,0 @@
1
- // Plan semantics. Stripe's Prices API "replaces the Plans API and is backwards compatible" (docs.stripe.com/api/plans/create),
2
- // and "Existing plans can be used wherever recurring prices are accepted", a plan being one "which can be used
3
- // interchangeably with a price" (docs.stripe.com/billing/migration/migrating-prices). So a plan is stored as the recurring
4
- // price it is, under the plan's id, and the Plans API answers recurring prices in the plan's shape: a plan made here is
5
- // read, listed, updated and subscribed to as a price, and a recurring price made through the Prices API is a plan.
6
- // The plan's id: "An identifier randomly generated by Stripe ... You can optionally override this ID, but the ID must be
7
- // unique across all plans in your Stripe account" (the create page's `id`). `amount_decimal` is "Same as `amount`, but
8
- // accepts a decimal value with at most 12 decimal places. Only one of `amount` and `amount_decimal` can be set", and the
9
- // plan answers it as "a decimal string", its `amount` "a whole integer if possible" (spec/openapi.json.gz, the plan
10
- // object). Plan writes send the plan events, plan.created / plan.updated / plan.deleted, each carrying the plan object
11
- // (docs.stripe.com/api/events/types; the write hook renders it, ../stripe-twin.ts afterStripeWrite). "Deleting plans
12
- // means new subscribers can't be added. Existing subscribers aren't affected." (docs.stripe.com/api/plans/delete), and
13
- // deleting one twice is an error. Where the documentation stops and the twin decides: a minted plan id is `plan_` over
14
- // the price counter, a duplicate id is refused with resource_already_exists, the refusals are worded by the twin, and only
15
- // the per_unit scheme is modelled (a tiered plan is refused, naming the gap); a deleted plan is gone from the Plans API
16
- // while the recurring price it was stays readable through the Prices API, inactive, so the subscription items that name
17
- // it still resolve (the docs do not say what the Prices API answers for it).
18
- import type { Semantics, SemanticsContext } from '@volter/world-core';
19
- import { asBool } from '../stripe-twin.ts';
20
- import { at, created, fail, kept, list, newest, type Row } from './shared.ts';
21
-
22
- const INTERVALS = new Set(['day', 'week', 'month', 'year']);
23
-
24
- /** A recurring price in the plan object's shape (the create page's example response). */
25
- export function planOf(price: Row): Row {
26
- const r = (price.recurring ?? {}) as Row;
27
- const amount = typeof price.unit_amount === 'number' ? price.unit_amount : null;
28
- const decimal = typeof price.unit_amount_decimal === 'string' ? price.unit_amount_decimal : amount === null ? null : String(amount);
29
- return {
30
- id: price.id, object: 'plan', active: price.active ?? true, amount, amount_decimal: decimal,
31
- billing_scheme: price.billing_scheme ?? 'per_unit', created: price.created, currency: price.currency, interval: r.interval ?? null,
32
- interval_count: r.interval_count ?? 1, livemode: false, metadata: price.metadata ?? {}, meter: r.meter ?? null, nickname: price.nickname ?? null,
33
- product: price.product, tiers_mode: price.tiers_mode ?? null, transform_usage: price.transform_quantity ?? null,
34
- trial_period_days: r.trial_period_days ?? null, usage_type: r.usage_type ?? 'licensed',
35
- };
36
- }
37
-
38
- /** Metadata after an update: an empty value unsets the key, an empty `metadata` unsets them all. */
39
- function metadataAfter(was: Row, given: unknown): Row {
40
- if (given === '' || given === null || typeof given !== 'object') return {};
41
- const next: Row = { ...was };
42
- for (const [k, v] of Object.entries(given as Row)) if (v === '' || v === null) delete next[k]; else next[k] = v;
43
- return next;
44
- }
45
-
46
- const planMissing = (ctx: SemanticsContext, id: string): Response => fail(ctx, `No such plan: '${id}'`, 404, 'resource_missing');
47
- /** A recurring price the Plans API still answers: one whose plan was deleted is not a plan any more. */
48
- const recurring = (ctx: SemanticsContext, p: Row | undefined): p is Row => !!p && !!p.recurring && kept(ctx, 'price', p, '_plan_deleted') !== true;
49
-
50
- const createPlan: Semantics = async (ctx) => {
51
- const p = ctx.params;
52
- for (const name of ['currency', 'interval', 'product']) if (p[name] === undefined || p[name] === '') return fail(ctx, `Missing required param: ${name}.`, 400, 'parameter_missing');
53
- if (!INTERVALS.has(String(p.interval))) return fail(ctx, `Invalid interval: must be one of day, week, month, or year`, 400, 'parameter_invalid_string');
54
- if (p.billing_scheme === 'tiered') return fail(ctx, 'Tiered plans are not modelled by this twin; create a tiered price instead.', 400, 'parameter_invalid_string');
55
- if (p.amount === undefined && p.amount_decimal === undefined) return fail(ctx, 'Missing required param: amount.', 400, 'parameter_missing');
56
- if (p.amount !== undefined && p.amount_decimal !== undefined) return fail(ctx, 'Only one of `amount` and `amount_decimal` can be set.', 400, 'parameter_invalid');
57
- const id = typeof p.id === 'string' && p.id ? p.id : ctx.mint('price').replace(/^price_/, 'plan_');
58
- if (ctx.get('price', id)) return fail(ctx, `Plan already exists: '${id}'`, 400, 'resource_already_exists');
59
- // "The product whose pricing the created plan will represent. This can either be the ID of an existing product, or a
60
- // dictionary containing fields used to create a service product"
61
- let product: string;
62
- if (p.product && typeof p.product === 'object') {
63
- product = String((await created(ctx, 'product', p.product as Row, { active: true, livemode: false, images: [], marketing_features: [], metadata: {}, updated: ctx.now() })).id);
64
- } else {
65
- product = String(p.product);
66
- if (!ctx.get('product', product)) return fail(ctx, `No such product: '${product}'`, 400, 'resource_missing');
67
- }
68
- // the decimal is kept as given; the whole amount is its integer when it is one
69
- const decimal = p.amount_decimal !== undefined ? String(p.amount_decimal) : String(Math.trunc(Number(p.amount)));
70
- const unit = Number.isInteger(Number(decimal)) ? Number(decimal) : null;
71
- const price = await created(ctx, 'price', {
72
- id, product, currency: String(p.currency).toLowerCase(), unit_amount: unit, unit_amount_decimal: decimal,
73
- recurring: { interval: p.interval, interval_count: Math.trunc(Number(p.interval_count ?? 1)), usage_type: p.usage_type ?? 'licensed', trial_period_days: p.trial_period_days !== undefined ? Math.trunc(Number(p.trial_period_days)) : null, meter: p.meter ?? null },
74
- ...(p.nickname !== undefined ? { nickname: p.nickname } : {}), ...(p.metadata !== undefined ? { metadata: p.metadata } : {}),
75
- ...(p.active !== undefined ? { active: asBool(p.active) } : {}),
76
- }, { active: true, livemode: false, billing_scheme: 'per_unit', type: 'recurring', metadata: {}, lookup_key: null, nickname: null, tax_behavior: 'unspecified' }, { operation: 'plan.create' });
77
- return ctx.reply(planOf(price));
78
- };
79
-
80
- const retrievePlan: Semantics = async (ctx) => {
81
- const price = ctx.get('price', at(ctx, 'plan'));
82
- return recurring(ctx, price) ? ctx.reply(planOf(price)) : planMissing(ctx, at(ctx, 'plan'));
83
- };
84
-
85
- // "Updates the specified plan by setting the values of the parameters passed. Any parameters not provided are left
86
- // unchanged. By design, you cannot change a plan's ID, amount, currency, or billing cycle." (docs.stripe.com/api/plans/update):
87
- // active, metadata ("Individual keys can be unset by posting an empty value to them. All keys can be unset by posting an
88
- // empty value to `metadata`"), nickname, product, trial_period_days
89
- const updatePlan: Semantics = async (ctx) => {
90
- const id = at(ctx, 'plan');
91
- const price = ctx.get('price', id);
92
- if (!recurring(ctx, price)) return planMissing(ctx, id);
93
- const p = ctx.params;
94
- if (typeof p.product === 'string' && !ctx.get('product', p.product)) return fail(ctx, `No such product: '${p.product}'`, 400, 'resource_missing');
95
- const fields: Row = {
96
- ...(p.active !== undefined ? { active: asBool(p.active) } : {}),
97
- ...(p.nickname !== undefined ? { nickname: p.nickname } : {}),
98
- ...(p.metadata !== undefined ? { metadata: metadataAfter((price.metadata ?? {}) as Row, p.metadata) } : {}),
99
- ...(typeof p.product === 'string' ? { product: p.product } : {}),
100
- ...(p.trial_period_days !== undefined ? { recurring: { ...(price.recurring as Row), trial_period_days: Math.trunc(Number(p.trial_period_days)) } } : {}),
101
- };
102
- const next = await ctx.write('price', id, fields, 'plan.update');
103
- return ctx.reply(planOf(next));
104
- };
105
-
106
- const deletePlan: Semantics = async (ctx) => {
107
- const id = at(ctx, 'plan');
108
- if (!recurring(ctx, ctx.get('price', id))) return planMissing(ctx, id);
109
- // existing subscribers keep it: the price stays, inactive, and only the plan is gone
110
- const price = ctx.get('price', id)!;
111
- if (price.active !== false) ctx.legal('price', 'active', 'DeletePlansPlan', 'true', 'false', id);
112
- await ctx.write('price', id, { active: false, _plan_deleted: true }, 'plan.delete');
113
- return ctx.reply({ id, object: 'plan', deleted: true });
114
- };
115
-
116
- const listPlans: Semantics = async (ctx) => {
117
- const p = ctx.params;
118
- const plans = newest(ctx, 'price').filter((x) => recurring(ctx, x))
119
- .filter((x) => p.active === undefined || asBool(x.active) === asBool(p.active))
120
- .filter((x) => p.product === undefined || x.product === p.product)
121
- .map(planOf);
122
- return list(ctx, 'price', plans);
123
- };
124
-
125
- export const plans: Record<string, Semantics> = {
126
- PostPlans: createPlan,
127
- GetPlans: listPlans,
128
- GetPlansPlan: retrievePlan,
129
- PostPlansPlan: updatePlan,
130
- DeletePlansPlan: deletePlan,
131
- };
@@ -1,220 +0,0 @@
1
- // Semantics for Stripe's smaller products: Climate (a fixed product and supplier catalog, and
2
- // orders against it), Financial Connections (sessions, linked accounts, their transactions),
3
- // PAN forwarding requests, and Reporting (a report-type catalog and report runs, which the twin
4
- // completes at once). Lists and retrieves of what is stored are the derived core's.
5
- import type { Semantics, SemanticsContext } from '@volter/world-core';
6
- import { at, created, fail, list, newest, path, where, type Row } from './shared.ts';
7
-
8
- // ── Climate: Stripe's catalog is managed and account-independent. The twin serves the catalog Stripe's reference
9
- // publishes (docs.stripe.com/api/climate/product/object, /api/climate/supplier/object): Frontier's 2027 offtake
10
- // portfolio at $550 a ton plus Frontier's service fees of $16.50 (3%), 18,000 tons, from Charm Industrial.
11
- // Where the documentation stops and the twin decides: the catalog is that one product and supplier. ──
12
-
13
- const CLIMATE_SUPPLIERS = [
14
- { id: 'climsup_charm_industrial', name: 'Charm Industrial', removal_pathway: 'biomass_carbon_removal_and_storage', info_url: 'https://frontierclimate.com/portfolio/charm-industrial', locations: [{ city: 'San Francisco', country: 'US', latitude: 37.7749, longitude: -122.4194, region: 'CA' }] },
15
- ] as const;
16
- const CLIMATE_PRODUCTS = [
17
- { id: 'climsku_frontier_offtake_portfolio_2027', name: "Frontier's 2027 offtake portfolio", subtotal: 55000, fees: 1650, currency: 'usd', delivery_year: 2027, metric_tons_available: '18000', created: 1881439203, suppliers: ['climsup_charm_industrial'] },
18
- ] as const;
19
- const supplierView = (s: (typeof CLIMATE_SUPPLIERS)[number]): Row => ({ id: s.id, object: 'climate.supplier', name: s.name, removal_pathway: s.removal_pathway, info_url: s.info_url, locations: s.locations, livemode: false });
20
- const productView = (p: (typeof CLIMATE_PRODUCTS)[number]): Row => ({
21
- id: p.id, object: 'climate.product', name: p.name, livemode: false, delivery_year: p.delivery_year,
22
- metric_tons_available: p.metric_tons_available, created: p.created,
23
- current_prices_per_metric_ton: { [p.currency]: { amount_fees: p.fees, amount_subtotal: p.subtotal, amount_total: p.subtotal + p.fees } },
24
- suppliers: p.suppliers.map((id) => supplierView(CLIMATE_SUPPLIERS.find((s) => s.id === id)!)),
25
- });
26
- const catalog = (ctx: SemanticsContext, data: Row[]): Response => ctx.reply({ object: 'list', url: path(ctx), has_more: false, data });
27
-
28
- const climateProduct: Semantics = async (ctx) => {
29
- const p = CLIMATE_PRODUCTS.find((x) => x.id === at(ctx, 'product'));
30
- return p ? ctx.reply(productView(p)) : fail(ctx, `No such product: '${at(ctx, 'product')}'`, 404, 'resource_missing');
31
- };
32
- const climateSupplier: Semantics = async (ctx) => {
33
- const s = CLIMATE_SUPPLIERS.find((x) => x.id === at(ctx, 'supplier'));
34
- return s ? ctx.reply(supplierView(s)) : fail(ctx, `No such supplier: '${at(ctx, 'supplier')}'`, 404, 'resource_missing');
35
- };
36
-
37
- const ORDER = 'climate.order';
38
- const orderMissing = (ctx: SemanticsContext, id: string): Response => fail(ctx, `No such order: '${id}'`, 404, 'resource_missing');
39
-
40
- // exactly one of amount or metric_tons; Frontier's fees are the product's per-ton share (3%: the create page's
41
- // example charges 17 on a 550 subtotal, "Total amount of Frontier's service fees", the order object), rounded to the
42
- // cent; the order is confirmed when made and delivers in the product's delivery year
43
- const createOrder: Semantics = async (ctx) => {
44
- const product = typeof ctx.params.product === 'string' ? ctx.params.product : '';
45
- if (!product) return fail(ctx, 'Missing required param: product.', 400, 'parameter_missing');
46
- const prod = CLIMATE_PRODUCTS.find((x) => x.id === product);
47
- if (!prod) return fail(ctx, `No such product: '${product}'`, 400, 'resource_missing');
48
- const hasTons = ctx.params.metric_tons !== undefined;
49
- if (hasTons === (ctx.params.amount !== undefined)) return fail(ctx, 'You must provide exactly one of `amount` or `metric_tons`.', 400, 'parameter_missing');
50
- const metricTons = hasTons ? Number(ctx.params.metric_tons) : Number(ctx.params.amount) / prod.subtotal;
51
- const amountSubtotal = Math.round(metricTons * prod.subtotal);
52
- const amountFees = Math.round((amountSubtotal * prod.fees) / prod.subtotal);
53
- return ctx.reply(
54
- await created(ctx, ORDER, {}, {
55
- object: 'climate.order', livemode: false, status: 'confirmed', product, certificate: null,
56
- amount_subtotal: amountSubtotal, amount_fees: amountFees, amount_total: amountSubtotal + amountFees,
57
- currency: prod.currency, metric_tons: String(metricTons),
58
- beneficiary: ctx.params.beneficiary && typeof ctx.params.beneficiary === 'object' ? ctx.params.beneficiary : { public_name: 'Stripe Climate' },
59
- confirmed_at: ctx.now(), canceled_at: null, delivered_at: null, delayed_at: null,
60
- product_substituted_at: null, cancellation_reason: null,
61
- expected_delivery_year: prod.delivery_year,
62
- delivery_details: [], metadata: ctx.params.metadata && typeof ctx.params.metadata === 'object' ? ctx.params.metadata : {},
63
- }),
64
- );
65
- };
66
-
67
- const cancelOrder: Semantics = async (ctx) => {
68
- const id = at(ctx, 'order');
69
- const o = ctx.get(ORDER, id);
70
- if (!o) return orderMissing(ctx, id);
71
- const refused = ctx.legal(ORDER, 'status', 'PostClimateOrdersOrderCancel', o.status, undefined, id);
72
- if (refused) return ctx.refuse(refused);
73
- return ctx.reply(await ctx.write(ORDER, id, { status: 'canceled', canceled_at: ctx.now(), cancellation_reason: 'requested' }, 'climate_order.canceled'));
74
- };
75
-
76
- // only the beneficiary and metadata change
77
- const updateOrder: Semantics = async (ctx) => {
78
- const id = at(ctx, 'order');
79
- if (!ctx.get(ORDER, id)) return orderMissing(ctx, id);
80
- const patch: Row = {};
81
- if (ctx.params.beneficiary !== undefined) patch.beneficiary = ctx.params.beneficiary;
82
- if (ctx.params.metadata !== undefined) patch.metadata = ctx.params.metadata;
83
- return ctx.reply(await ctx.write(ORDER, id, patch, 'climate_order.updated'));
84
- };
85
-
86
- // ── Financial Connections: a session is created for an account holder and its permissions; accounts
87
- // are linked in the authentication flow Stripe.js opens (../screens/financial-connections.tsx) ──
88
-
89
- const FCS = 'financial_connections.session';
90
- const FCA = 'financial_connections.account';
91
- const FCT = 'financial_connections.transaction';
92
-
93
- const createSession: Semantics = async (ctx) => {
94
- const holder = ctx.params.account_holder && typeof ctx.params.account_holder === 'object' ? (ctx.params.account_holder as Row) : null;
95
- if (!holder) return fail(ctx, 'Missing required param: account_holder.', 400, 'parameter_missing');
96
- const perms = Array.isArray(ctx.params.permissions) ? ctx.params.permissions.map(String) : typeof ctx.params.permissions === 'string' ? [ctx.params.permissions] : [];
97
- if (perms.length === 0) return fail(ctx, 'Missing required param: permissions.', 400, 'parameter_missing');
98
- const id = ctx.mint(FCS);
99
- return ctx.reply(
100
- await created(ctx, FCS, { id }, {
101
- object: 'financial_connections.session', livemode: false, client_secret: `fcsess_${id}_secret_twin`,
102
- account_holder: holder, permissions: perms, prefetch: Array.isArray(ctx.params.prefetch) ? ctx.params.prefetch : null,
103
- filters: ctx.params.filters && typeof ctx.params.filters === 'object' ? ctx.params.filters : null,
104
- return_url: typeof ctx.params.return_url === 'string' ? ctx.params.return_url : null,
105
- accounts: { object: 'list', has_more: false, url: `/v1/financial_connections/accounts?session=${id}`, data: [] },
106
- }),
107
- );
108
- };
109
-
110
- // a session's accounts are the ones linked to it now
111
- const session: Semantics = async (ctx) => {
112
- const id = at(ctx, 'session');
113
- const s = ctx.get(FCS, id);
114
- if (!s) return fail(ctx, `No such financial connections session: '${id}'`, 404, 'resource_missing');
115
- return ctx.reply({ ...s, accounts: { object: 'list', has_more: false, url: `/v1/financial_connections/accounts?session=${id}`, data: newest(ctx, FCA).filter((a) => a.session === id) } });
116
- };
117
-
118
- const accounts: Semantics = async (ctx) =>
119
- list(ctx, FCA, where(ctx, newest(ctx, FCA), { session: (a, v) => a.session === v, account_holder: (a, v) => (a.account_holder as Row | undefined)?.customer === v }));
120
-
121
- const disconnect: Semantics = async (ctx) => {
122
- const id = at(ctx, 'account');
123
- const a = ctx.get(FCA, id);
124
- if (!a) return fail(ctx, `No such account: '${id}'`, 404, 'resource_missing');
125
- const refused = ctx.legal(FCA, 'status', 'PostFinancialConnectionsAccountsAccountDisconnect', a.status, undefined, id);
126
- if (refused) return ctx.refuse(refused);
127
- return ctx.reply(await ctx.write(FCA, id, { status: 'disconnected' }, 'fc_account.disconnected'));
128
- };
129
-
130
- const transactions: Semantics = async (ctx) => {
131
- if (typeof ctx.params.account !== 'string' || !ctx.params.account) return fail(ctx, 'Missing required param: account.', 400, 'parameter_missing');
132
- return list(ctx, FCT, newest(ctx, FCT).filter((t) => t.account === ctx.params.account));
133
- };
134
-
135
- // ── forwarding: the twin answers a deterministic destination response; it makes no network call ──
136
-
137
- const forward: Semantics = async (ctx) => {
138
- const pm = typeof ctx.params.payment_method === 'string' ? ctx.params.payment_method : '';
139
- if (!pm) return fail(ctx, 'Missing required param: payment_method.', 400, 'parameter_missing');
140
- const url = typeof ctx.params.url === 'string' ? ctx.params.url : '';
141
- if (!url) return fail(ctx, 'Missing required param: url.', 400, 'parameter_missing');
142
- return ctx.reply(
143
- await created(ctx, 'forwarding.request', {}, {
144
- object: 'forwarding.request', livemode: false, payment_method: pm, url, replacements: Array.isArray(ctx.params.replacements) ? ctx.params.replacements.map(String) : [],
145
- request_context: { destination_duration: 42, destination_ip_address: '127.0.0.1' },
146
- request_details: { http_method: 'POST', url, headers: [], body: '[redacted]' },
147
- response_details: { status: 200, headers: [], body: '{"approved":true}' },
148
- }),
149
- );
150
- };
151
-
152
- // ── Reporting: a representative subset of Stripe's report types; a run succeeds at once ──
153
-
154
- const REPORT_TYPES: Array<{ id: string; name: string }> = [
155
- { id: 'balance.summary.1', name: 'Balance summary' },
156
- { id: 'balance_change_from_activity.summary.1', name: 'Balance change from activity (summary)' },
157
- { id: 'payouts.summary.1', name: 'Payouts (summary)' },
158
- { id: 'payout_reconciliation.by_id.itemized.4', name: 'Payout reconciliation (itemized)' },
159
- ];
160
- const reportTypeView = (t: { id: string; name: string }): Row => ({
161
- id: t.id, object: 'reporting.report_type', name: t.name, version: 1,
162
- data_available_start: 0, data_available_end: 0, default_columns: null, updated: 0, livemode: false,
163
- });
164
-
165
- const reportType: Semantics = async (ctx) => {
166
- const t = REPORT_TYPES.find((x) => x.id === at(ctx, 'report_type'));
167
- return t ? ctx.reply(reportTypeView(t)) : fail(ctx, `No such report type: '${at(ctx, 'report_type')}'`, 404, 'resource_missing');
168
- };
169
-
170
- // report_type names the report; parameters (the interval, the columns) shape it (docs.stripe.com/api/reporting/report_run/create)
171
- const runReport: Semantics = async (ctx) => {
172
- const p = ctx.params.parameters && typeof ctx.params.parameters === 'object' ? (ctx.params.parameters as Row) : {};
173
- const type = typeof ctx.params.report_type === 'string' ? ctx.params.report_type : '';
174
- if (!type) return fail(ctx, 'Missing required param: report_type.', 400, 'parameter_missing');
175
- if (!REPORT_TYPES.some((t) => t.id === type)) return fail(ctx, `Invalid report type: '${type}'.`, 400, 'parameter_invalid_string_enum');
176
- // a run starts pending with no result (finishReportRuns completes it)
177
- return ctx.reply(await created(ctx, 'reporting.report_run', { parameters: p }, { status: 'pending', report_type: type, livemode: false, error: null, succeeded_at: null, result: null }));
178
- };
179
-
180
- /** Each pending report run completes, caught up before anything is answered: "When the run completes, Stripe updates
181
- * the object, and it has a status of succeeded. It also has a nested result object, containing a URL that you can use
182
- * to access the file", the guide's example a File of purpose report_run and type csv (docs.stripe.com/reports/api).
183
- * "Most runs complete within a few minutes" (the same page). Where the documentation stops and the twin decides: a run
184
- * completes one minute after it was created (the guide's example: created 1580832900, succeeded_at 1580832960), and
185
- * its CSV holds the report type's header row alone (its size that row's bytes). */
186
- export async function finishReportRuns(ctx: SemanticsContext): Promise<void> {
187
- for (const run of ctx.rowsRaw('reporting.report_run')) {
188
- if (run.status !== 'pending') continue;
189
- const done = Number(run.created) + 60;
190
- if (Number(ctx.now()) < done) continue;
191
- const id = String(run.id);
192
- const header = 'category,currency,description,net_amount\n';
193
- const file = await created(ctx, 'file', { purpose: 'report_run' }, {
194
- filename: `${String(run.report_type)}_${id}.csv`, size: header.length, type: 'csv', title: null, expires_at: null, url: null,
195
- links: { object: 'list', data: [], has_more: false, url: '' },
196
- });
197
- await ctx.write('file', String(file.id), { url: `https://files.twin.local/v1/files/${String(file.id)}/contents` }, 'file.updated');
198
- ctx.legal('reporting.report_run', 'status', ctx.call.operation.id, 'pending', 'succeeded', id, 'vendor');
199
- await ctx.write('reporting.report_run', id, { status: 'succeeded', succeeded_at: done, result: ctx.get('file', String(file.id)) }, 'reporting.report_run.succeeded');
200
- }
201
- }
202
-
203
- export const platform: Record<string, Semantics> = {
204
- GetClimateProducts: async (ctx) => catalog(ctx, CLIMATE_PRODUCTS.map(productView)),
205
- GetClimateProductsProduct: climateProduct,
206
- GetClimateSuppliers: async (ctx) => catalog(ctx, CLIMATE_SUPPLIERS.map(supplierView)),
207
- GetClimateSuppliersSupplier: climateSupplier,
208
- PostClimateOrders: createOrder,
209
- PostClimateOrdersOrderCancel: cancelOrder,
210
- PostClimateOrdersOrder: updateOrder,
211
- PostFinancialConnectionsSessions: createSession,
212
- GetFinancialConnectionsSessionsSession: session,
213
- GetFinancialConnectionsAccounts: accounts,
214
- PostFinancialConnectionsAccountsAccountDisconnect: disconnect,
215
- GetFinancialConnectionsTransactions: transactions,
216
- PostForwardingRequests: forward,
217
- GetReportingReportTypes: async (ctx) => catalog(ctx, REPORT_TYPES.map(reportTypeView)),
218
- GetReportingReportTypesReportType: reportType,
219
- PostReportingReportRuns: runReport,
220
- };