@volter/twin-stripe 2.0.38 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +82 -207
- package/dist/generated/pack-facts.json +94 -0
- package/dist/spec/SOURCE.md +14 -0
- package/dist/spec/fixtures3.json.gz +0 -0
- package/dist/spec/openapi.json.gz +0 -0
- package/dist/spec/patches.json +34 -0
- package/dist/spec/sources.json +378 -0
- package/dist/src/cli.js +12 -30
- package/dist/src/engine/after-payment.d.ts +9 -0
- package/dist/src/engine/after-payment.js +28 -0
- package/dist/src/engine/apps-secrets.d.ts +1 -0
- package/dist/src/engine/apps-secrets.js +3 -0
- package/dist/src/engine/balance.d.ts +5 -0
- package/dist/src/engine/balance.js +15 -0
- package/dist/src/engine/billing.d.ts +5 -0
- package/dist/src/engine/billing.js +6 -0
- package/dist/src/engine/charges.d.ts +6 -0
- package/dist/src/engine/charges.js +13 -0
- package/dist/src/engine/checkout.d.ts +24 -0
- package/dist/src/engine/checkout.js +30 -0
- package/dist/src/engine/common.d.ts +19 -0
- package/dist/src/engine/common.js +32 -0
- package/dist/src/{screens → engine}/connect-settings.d.ts +1 -7
- package/dist/src/engine/connect-settings.js +26 -0
- package/dist/src/engine/connect.d.ts +66 -0
- package/dist/src/engine/connect.js +189 -0
- package/dist/src/engine/coupons.d.ts +0 -0
- package/dist/src/engine/coupons.js +5 -0
- package/dist/src/engine/credit-notes.d.ts +1 -0
- package/dist/src/engine/credit-notes.js +5 -0
- package/dist/src/engine/customers.d.ts +12 -0
- package/dist/src/engine/customers.js +30 -0
- package/dist/src/engine/display.d.ts +14 -0
- package/dist/src/engine/display.js +16 -0
- package/dist/src/engine/disputes.d.ts +0 -0
- package/dist/src/engine/disputes.js +9 -0
- package/dist/src/engine/entitlements.d.ts +1 -0
- package/dist/src/engine/entitlements.js +4 -0
- package/dist/src/engine/ephemeral-keys.d.ts +0 -0
- package/dist/src/engine/ephemeral-keys.js +4 -0
- package/dist/src/engine/files.d.ts +18 -0
- package/dist/src/engine/files.js +33 -0
- package/dist/src/engine/front.d.ts +5 -0
- package/dist/src/engine/front.js +25 -0
- package/dist/src/engine/invoices.d.ts +24 -0
- package/dist/src/engine/invoices.js +57 -0
- package/dist/src/engine/issuing.d.ts +35 -0
- package/dist/src/engine/issuing.js +45 -0
- package/dist/src/engine/ledger.d.ts +9 -0
- package/dist/src/engine/ledger.js +9 -0
- package/dist/src/engine/oauth.d.ts +4 -0
- package/dist/src/engine/oauth.js +25 -0
- package/dist/src/engine/onboarding.d.ts +13 -0
- package/dist/src/engine/onboarding.js +42 -0
- package/dist/src/{stripe-params.d.ts → engine/params.d.ts} +20 -3
- package/dist/src/{stripe-params.js → engine/params.js} +7 -60
- package/dist/src/engine/payment-intents.d.ts +10 -0
- package/dist/src/engine/payment-intents.js +27 -0
- package/dist/src/engine/payment-links.d.ts +1 -0
- package/dist/src/engine/payment-links.js +5 -0
- package/dist/src/engine/payment-methods.d.ts +16 -0
- package/dist/src/engine/payment-methods.js +22 -0
- package/dist/src/engine/plans.d.ts +6 -0
- package/dist/src/engine/plans.js +26 -0
- package/dist/src/engine/platform.d.ts +39 -0
- package/dist/src/engine/platform.js +34 -0
- package/dist/src/engine/products.d.ts +0 -0
- package/dist/src/engine/products.js +4 -0
- package/dist/src/engine/radar.d.ts +2 -0
- package/dist/src/engine/radar.js +5 -0
- package/dist/src/engine/refunds.d.ts +1 -0
- package/dist/src/engine/refunds.js +28 -0
- package/dist/src/engine/renewals.d.ts +36 -0
- package/dist/src/engine/renewals.js +65 -0
- package/dist/src/engine/setup-intents.d.ts +1 -0
- package/dist/src/engine/setup-intents.js +4 -0
- package/dist/src/{stripe-twin.d.ts → engine/stripe.d.ts} +11 -39
- package/dist/src/{stripe-twin.js → engine/stripe.js} +25 -310
- package/dist/src/engine/subscription-schedules.d.ts +3 -0
- package/dist/src/engine/subscription-schedules.js +1 -0
- package/dist/src/engine/subscriptions.d.ts +12 -0
- package/dist/src/engine/subscriptions.js +31 -0
- package/dist/src/engine/tax.d.ts +7 -0
- package/dist/src/engine/tax.js +28 -0
- package/dist/src/engine/terminal.d.ts +4 -0
- package/dist/src/engine/terminal.js +20 -0
- package/dist/src/engine/test-clocks.d.ts +5 -0
- package/dist/src/engine/test-clocks.js +9 -0
- package/dist/src/engine/tokens.d.ts +7 -0
- package/dist/src/engine/tokens.js +20 -0
- package/dist/src/engine/transfers.d.ts +2 -0
- package/dist/src/engine/transfers.js +1 -0
- package/dist/src/engine/treasury.d.ts +23 -0
- package/dist/src/engine/treasury.js +45 -0
- package/dist/src/{stripe-version.js → engine/version.js} +4 -3
- package/dist/src/engine/webhook-endpoints.d.ts +1 -0
- package/dist/src/engine/webhook-endpoints.js +12 -0
- package/dist/src/engine/webhooks.d.ts +31 -0
- package/dist/src/engine/webhooks.js +68 -0
- package/dist/src/fetch.d.ts +2 -0
- package/dist/src/fetch.js +26 -0
- package/dist/src/generated/surface.gen.json +1 -1
- package/dist/src/generated/ui.gen.json +1 -1
- package/dist/src/index.d.ts +5 -14
- package/dist/src/index.js +8 -75
- package/dist/src/manifest.js +232 -758
- package/dist/src/screens/billing-portal.d.ts +3 -0
- package/dist/src/screens/{portal.js → billing-portal.js} +28 -54
- package/dist/src/screens/checkout.d.ts +2 -31
- package/dist/src/screens/checkout.js +32 -121
- package/dist/src/screens/connect-oauth.d.ts +3 -27
- package/dist/src/screens/connect-oauth.js +51 -132
- package/dist/src/screens/connect-onboarding.d.ts +3 -0
- package/dist/src/screens/{onboarding.js → connect-onboarding.js} +36 -102
- package/dist/src/screens/dashboard.d.ts +3 -0
- package/dist/src/screens/dashboard.js +117 -0
- package/dist/src/screens/shared.d.ts +27 -0
- package/dist/src/screens/shared.js +87 -0
- package/dist/src/screens/stripe-js.d.ts +3 -0
- package/dist/src/screens/stripe-js.js +135 -0
- package/dist/src/semantics/account_links.d.ts +2 -0
- package/dist/src/semantics/account_links.js +22 -0
- package/dist/src/semantics/accounts.d.ts +4 -0
- package/dist/src/semantics/accounts.js +38 -0
- package/dist/src/semantics/apps.d.ts +4 -0
- package/dist/src/semantics/{apps-secrets.js → apps.js} +14 -26
- package/dist/src/semantics/around.d.ts +2 -0
- package/dist/src/semantics/around.js +16 -0
- package/dist/src/semantics/balance.d.ts +2 -11
- package/dist/src/semantics/balance.js +3 -194
- package/dist/src/semantics/balance_transactions.d.ts +2 -0
- package/dist/src/semantics/balance_transactions.js +15 -0
- package/dist/src/semantics/billing_portal.d.ts +5 -0
- package/dist/src/semantics/billing_portal.js +42 -0
- package/dist/src/semantics/charges.d.ts +3 -28
- package/dist/src/semantics/charges.js +5 -202
- package/dist/src/semantics/checkout.d.ts +3 -20
- package/dist/src/semantics/checkout.js +8 -261
- package/dist/src/semantics/clock.d.ts +2 -0
- package/dist/src/semantics/clock.js +21 -0
- package/dist/src/semantics/coupons.d.ts +2 -6
- package/dist/src/semantics/coupons.js +2 -60
- package/dist/src/semantics/customers.d.ts +6 -6
- package/dist/src/semantics/customers.js +27 -387
- package/dist/src/semantics/disputes.d.ts +2 -2
- package/dist/src/semantics/disputes.js +3 -49
- package/dist/src/semantics/doors.d.ts +23 -0
- package/dist/src/semantics/doors.js +73 -0
- package/dist/src/semantics/entitlements.d.ts +2 -2
- package/dist/src/semantics/entitlements.js +5 -50
- package/dist/src/semantics/events.d.ts +12 -0
- package/dist/src/semantics/events.js +36 -0
- package/dist/src/semantics/index.d.ts +2 -0
- package/dist/src/semantics/index.js +107 -0
- package/dist/src/semantics/invoice_payments.d.ts +2 -0
- package/dist/src/semantics/invoice_payments.js +12 -0
- package/dist/src/semantics/invoiceitems.d.ts +3 -0
- package/dist/src/semantics/invoiceitems.js +59 -0
- package/dist/src/semantics/invoices.d.ts +16 -18
- package/dist/src/semantics/invoices.js +118 -444
- package/dist/src/semantics/payment_intents.d.ts +4 -0
- package/dist/src/semantics/payment_intents.js +79 -0
- package/dist/src/semantics/payment_methods.d.ts +5 -0
- package/dist/src/semantics/payment_methods.js +39 -0
- package/dist/src/semantics/payouts.d.ts +2 -0
- package/dist/src/semantics/payouts.js +21 -0
- package/dist/src/semantics/prices.d.ts +4 -0
- package/dist/src/semantics/prices.js +37 -0
- package/dist/src/semantics/products.d.ts +6 -2
- package/dist/src/semantics/products.js +15 -130
- package/dist/src/semantics/promotion_codes.d.ts +3 -0
- package/dist/src/semantics/promotion_codes.js +35 -0
- package/dist/src/semantics/radar.d.ts +2 -2
- package/dist/src/semantics/radar.js +5 -74
- package/dist/src/semantics/refunds.d.ts +3 -9
- package/dist/src/semantics/refunds.js +6 -192
- package/dist/src/semantics/setup_intents.d.ts +3 -0
- package/dist/src/semantics/{setup-intents.js → setup_intents.js} +10 -53
- package/dist/src/semantics/shared.d.ts +822 -47
- package/dist/src/semantics/shared.js +3044 -78
- package/dist/src/semantics/states.d.ts +531 -0
- package/dist/src/semantics/states.js +852 -0
- package/dist/src/semantics/subscription_items.d.ts +5 -0
- package/dist/src/semantics/subscription_items.js +55 -0
- package/dist/src/semantics/subscription_schedules.d.ts +4 -0
- package/dist/src/semantics/subscription_schedules.js +60 -0
- package/dist/src/semantics/subscriptions.d.ts +7 -11
- package/dist/src/semantics/subscriptions.js +44 -415
- package/dist/src/semantics/test_helpers.d.ts +6 -0
- package/dist/src/semantics/{test-clocks.js → test_helpers.js} +14 -40
- package/dist/src/semantics/transfers.d.ts +2 -2
- package/dist/src/semantics/transfers.js +6 -101
- package/dist/src/server.d.ts +7 -0
- package/dist/src/server.js +7 -0
- package/generated/pack-facts.json +94 -0
- package/package.json +10 -20
- package/spec/SOURCE.md +14 -0
- package/spec/fixtures3.json.gz +0 -0
- package/spec/openapi.json.gz +0 -0
- package/spec/patches.json +34 -0
- package/spec/sources.json +378 -0
- package/src/cli.ts +12 -26
- package/src/engine/after-payment.ts +31 -0
- package/src/engine/apps-secrets.ts +4 -0
- package/src/engine/balance.ts +33 -0
- package/src/engine/billing.ts +16 -0
- package/src/engine/charges.ts +19 -0
- package/src/engine/checkout.ts +40 -0
- package/src/engine/common.ts +47 -0
- package/src/engine/connect-settings.ts +23 -0
- package/src/engine/connect.ts +184 -0
- package/src/engine/coupons.ts +5 -0
- package/src/engine/credit-notes.ts +6 -0
- package/src/engine/customers.ts +35 -0
- package/src/engine/display.ts +19 -0
- package/src/engine/disputes.ts +9 -0
- package/src/engine/entitlements.ts +5 -0
- package/src/engine/ephemeral-keys.ts +3 -0
- package/src/engine/files.ts +41 -0
- package/src/engine/front.ts +31 -0
- package/src/engine/invoices.ts +71 -0
- package/src/engine/issuing.ts +61 -0
- package/src/engine/ledger.ts +50 -0
- package/src/engine/oauth.ts +19 -0
- package/src/engine/onboarding.ts +54 -0
- package/src/{stripe-params.ts → engine/params.ts} +8 -56
- package/src/engine/payment-intents.ts +33 -0
- package/src/engine/payment-links.ts +6 -0
- package/src/engine/payment-methods.ts +25 -0
- package/src/engine/plans.ts +42 -0
- package/src/engine/platform.ts +47 -0
- package/src/engine/products.ts +3 -0
- package/src/engine/radar.ts +6 -0
- package/src/engine/refunds.ts +29 -0
- package/src/engine/renewals.ts +73 -0
- package/src/engine/setup-intents.ts +5 -0
- package/src/{stripe-twin.ts → engine/stripe.ts} +28 -323
- package/src/engine/subscription-schedules.ts +10 -0
- package/src/engine/subscriptions.ts +40 -0
- package/src/engine/tax.ts +39 -0
- package/src/engine/terminal.ts +23 -0
- package/src/engine/test-clocks.ts +11 -0
- package/src/engine/tokens.ts +22 -0
- package/src/engine/transfers.ts +23 -0
- package/src/engine/treasury.ts +47 -0
- package/src/{stripe-version.ts → engine/version.ts} +4 -3
- package/src/engine/webhook-endpoints.ts +14 -0
- package/src/engine/webhooks.ts +72 -0
- package/src/fetch.ts +27 -0
- package/src/generated/surface.gen.json +1 -1
- package/src/generated/ui.gen.json +1 -1
- package/src/index.ts +8 -116
- package/src/manifest.ts +234 -786
- package/src/screens/{portal.tsx → billing-portal.tsx} +32 -37
- package/src/screens/checkout.tsx +33 -95
- package/src/screens/connect-oauth.tsx +64 -88
- package/src/screens/{onboarding.tsx → connect-onboarding.tsx} +38 -82
- package/src/screens/dashboard.tsx +198 -0
- package/src/screens/shared.tsx +84 -0
- package/src/screens/stripe-js.ts +170 -0
- package/src/semantics/account_links.ts +21 -0
- package/src/semantics/accounts.ts +43 -0
- package/src/semantics/{apps-secrets.ts → apps.ts} +17 -32
- package/src/semantics/around.ts +20 -0
- package/src/semantics/balance.ts +6 -207
- package/src/semantics/balance_transactions.ts +20 -0
- package/src/semantics/billing_portal.ts +51 -0
- package/src/semantics/charges.ts +12 -211
- package/src/semantics/checkout.ts +13 -268
- package/src/semantics/clock.ts +26 -0
- package/src/semantics/coupons.ts +5 -67
- package/src/semantics/customers.ts +29 -392
- package/src/semantics/disputes.ts +9 -59
- package/src/semantics/doors.ts +80 -0
- package/src/semantics/entitlements.ts +9 -56
- package/src/semantics/events.ts +44 -0
- package/src/semantics/index.ts +111 -0
- package/src/semantics/invoice_payments.ts +18 -0
- package/src/semantics/invoiceitems.ts +59 -0
- package/src/semantics/invoices.ts +109 -443
- package/src/semantics/payment_intents.ts +83 -0
- package/src/semantics/payment_methods.ts +43 -0
- package/src/semantics/payouts.ts +23 -0
- package/src/semantics/prices.ts +42 -0
- package/src/semantics/products.ts +18 -142
- package/src/semantics/promotion_codes.ts +39 -0
- package/src/semantics/radar.ts +8 -77
- package/src/semantics/refunds.ts +9 -212
- package/src/semantics/setup_intents.ts +45 -0
- package/src/semantics/shared.ts +3092 -106
- package/src/semantics/states.ts +883 -0
- package/src/semantics/subscription_items.ts +54 -0
- package/src/semantics/subscription_schedules.ts +66 -0
- package/src/semantics/subscriptions.ts +49 -432
- package/src/semantics/{test-clocks.ts → test_helpers.ts} +23 -47
- package/src/semantics/transfers.ts +11 -131
- package/src/server.ts +8 -0
- package/client/dashboard-api.ts +0 -286
- package/client/stripe-mirror.css +0 -277
- package/client/stripe-mirror.tsx +0 -1559
- package/dist/client/dashboard-api.d.ts +0 -107
- package/dist/client/dashboard-api.js +0 -238
- package/dist/client/dashboard-api.ts +0 -286
- package/dist/client/stripe-mirror.bundle.js +0 -236
- package/dist/client/stripe-mirror.css +0 -277
- package/dist/client/stripe-mirror.d.ts +0 -134
- package/dist/client/stripe-mirror.js +0 -859
- package/dist/client/stripe-mirror.tsx +0 -1559
- package/dist/src/screens/connect-settings.js +0 -103
- package/dist/src/screens/consent-skin.d.ts +0 -4
- package/dist/src/screens/consent-skin.js +0 -18
- package/dist/src/screens/financial-connections.d.ts +0 -5
- package/dist/src/screens/financial-connections.js +0 -90
- package/dist/src/screens/identity.d.ts +0 -5
- package/dist/src/screens/identity.js +0 -86
- package/dist/src/screens/onboarding.d.ts +0 -13
- package/dist/src/screens/portal.d.ts +0 -5
- package/dist/src/screens/public-details.d.ts +0 -5
- package/dist/src/screens/public-details.js +0 -90
- package/dist/src/semantics/after-payment.d.ts +0 -22
- package/dist/src/semantics/after-payment.js +0 -99
- package/dist/src/semantics/apps-secrets.d.ts +0 -2
- package/dist/src/semantics/billing.d.ts +0 -2
- package/dist/src/semantics/billing.js +0 -220
- package/dist/src/semantics/connect.d.ts +0 -5
- package/dist/src/semantics/connect.js +0 -493
- package/dist/src/semantics/credit-notes.d.ts +0 -2
- package/dist/src/semantics/credit-notes.js +0 -172
- package/dist/src/semantics/ephemeral-keys.d.ts +0 -2
- package/dist/src/semantics/ephemeral-keys.js +0 -34
- package/dist/src/semantics/files.d.ts +0 -2
- package/dist/src/semantics/files.js +0 -125
- package/dist/src/semantics/issuing.d.ts +0 -13
- package/dist/src/semantics/issuing.js +0 -575
- package/dist/src/semantics/ledger.d.ts +0 -59
- package/dist/src/semantics/ledger.js +0 -200
- package/dist/src/semantics/payment-intents.d.ts +0 -18
- package/dist/src/semantics/payment-intents.js +0 -452
- package/dist/src/semantics/payment-links.d.ts +0 -2
- package/dist/src/semantics/payment-links.js +0 -133
- package/dist/src/semantics/payment-methods.d.ts +0 -20
- package/dist/src/semantics/payment-methods.js +0 -140
- package/dist/src/semantics/plans.d.ts +0 -5
- package/dist/src/semantics/plans.js +0 -121
- package/dist/src/semantics/platform.d.ts +0 -9
- package/dist/src/semantics/platform.js +0 -206
- package/dist/src/semantics/renewals.d.ts +0 -47
- package/dist/src/semantics/renewals.js +0 -281
- package/dist/src/semantics/setup-intents.d.ts +0 -2
- package/dist/src/semantics/subscription-schedules.d.ts +0 -2
- package/dist/src/semantics/subscription-schedules.js +0 -119
- package/dist/src/semantics/tax.d.ts +0 -2
- package/dist/src/semantics/tax.js +0 -197
- package/dist/src/semantics/terminal.d.ts +0 -5
- package/dist/src/semantics/terminal.js +0 -182
- package/dist/src/semantics/test-clocks.d.ts +0 -6
- package/dist/src/semantics/tokens.d.ts +0 -4
- package/dist/src/semantics/tokens.js +0 -44
- package/dist/src/semantics/treasury.d.ts +0 -2
- package/dist/src/semantics/treasury.js +0 -377
- package/dist/src/semantics/webhook-endpoints.d.ts +0 -3
- package/dist/src/semantics/webhook-endpoints.js +0 -85
- package/dist/src/stripe-budget.d.ts +0 -55
- package/dist/src/stripe-budget.js +0 -155
- package/dist/src/stripe-capabilities.d.ts +0 -3
- package/dist/src/stripe-capabilities.js +0 -5836
- package/dist/src/stripe-conformance.d.ts +0 -43
- package/dist/src/stripe-conformance.js +0 -105
- package/dist/src/stripe-connector.d.ts +0 -161
- package/dist/src/stripe-connector.js +0 -414
- package/dist/src/stripe-emit.d.ts +0 -2
- package/dist/src/stripe-emit.js +0 -145
- package/dist/src/stripe-events.d.ts +0 -93
- package/dist/src/stripe-events.js +0 -392
- package/dist/src/stripe-js.d.ts +0 -4
- package/dist/src/stripe-js.js +0 -70
- package/dist/src/stripe-mirror-ui.d.ts +0 -15
- package/dist/src/stripe-mirror-ui.js +0 -87
- package/dist/src/stripe-perform-harness.d.ts +0 -9
- package/dist/src/stripe-perform-harness.js +0 -26
- package/dist/src/stripe-server.d.ts +0 -33
- package/dist/src/stripe-server.js +0 -429
- package/dist/src/stripe-shared.d.ts +0 -109
- package/dist/src/stripe-shared.js +0 -276
- package/dist/src/stripe-ui-conformance.d.ts +0 -5
- package/dist/src/stripe-ui-conformance.js +0 -79
- package/dist/src/stripe-ui-structure.d.ts +0 -3
- package/dist/src/stripe-ui-structure.js +0 -168
- package/dist/test-fixtures/stripe-known-deviations.json +0 -110
- package/dist/test-fixtures/stripe-openapi-operations.SOURCE.md +0 -14
- package/dist/test-fixtures/stripe-openapi-operations.json +0 -4717
- package/dist/test-fixtures/stripe-schemas.SOURCE.md +0 -35
- package/dist/test-fixtures/stripe-schemas.json +0 -3813
- package/src/screens/connect-settings.tsx +0 -121
- package/src/screens/consent-skin.ts +0 -20
- package/src/screens/financial-connections.tsx +0 -101
- package/src/screens/identity.tsx +0 -96
- package/src/screens/public-details.tsx +0 -105
- package/src/semantics/after-payment.ts +0 -118
- package/src/semantics/billing.ts +0 -216
- package/src/semantics/connect.ts +0 -487
- package/src/semantics/credit-notes.ts +0 -168
- package/src/semantics/ephemeral-keys.ts +0 -34
- package/src/semantics/files.ts +0 -143
- package/src/semantics/issuing.ts +0 -590
- package/src/semantics/ledger.ts +0 -253
- package/src/semantics/payment-intents.ts +0 -463
- package/src/semantics/payment-links.ts +0 -148
- package/src/semantics/payment-methods.ts +0 -145
- package/src/semantics/plans.ts +0 -131
- package/src/semantics/platform.ts +0 -220
- package/src/semantics/renewals.ts +0 -279
- package/src/semantics/setup-intents.ts +0 -87
- package/src/semantics/subscription-schedules.ts +0 -129
- package/src/semantics/tax.ts +0 -220
- package/src/semantics/terminal.ts +0 -195
- package/src/semantics/tokens.ts +0 -52
- package/src/semantics/treasury.ts +0 -383
- package/src/semantics/webhook-endpoints.ts +0 -87
- package/src/stripe-budget.ts +0 -181
- package/src/stripe-capabilities.ts +0 -5651
- package/src/stripe-conformance.ts +0 -124
- package/src/stripe-connector.ts +0 -462
- package/src/stripe-emit.ts +0 -157
- package/src/stripe-events.ts +0 -434
- package/src/stripe-js.ts +0 -70
- package/src/stripe-mirror-ui.ts +0 -90
- package/src/stripe-perform-harness.ts +0 -29
- package/src/stripe-server.ts +0 -393
- package/src/stripe-shared.ts +0 -297
- package/src/stripe-ui-conformance.ts +0 -88
- package/src/stripe-ui-structure.ts +0 -182
- package/test-fixtures/stripe-known-deviations.json +0 -110
- package/test-fixtures/stripe-openapi-operations.json +0 -4717
- package/test-fixtures/stripe-schemas.json +0 -3813
- /package/dist/src/{screens → engine}/industries.d.ts +0 -0
- /package/dist/src/{screens → engine}/industries.js +0 -0
- /package/dist/src/{semantics → engine}/test-cards.d.ts +0 -0
- /package/dist/src/{semantics → engine}/test-cards.js +0 -0
- /package/dist/src/{stripe-version.d.ts → engine/version.d.ts} +0 -0
- /package/src/{screens → engine}/industries.ts +0 -0
- /package/src/{semantics → engine}/test-cards.ts +0 -0
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
// What a connected account owes Stripe before it can take payments (the requirements its onboarding collects,
|
|
2
|
+
// ../screens/connect-onboarding.tsx), as the Accounts API reports them (`requirements.currently_due`): the two US sets the twin
|
|
3
|
+
// models, a company's and an individual's.
|
|
4
|
+
import { INDUSTRIES as MCCS } from './industries.ts';
|
|
5
|
+
|
|
6
|
+
type Row = Record<string, unknown>;
|
|
7
|
+
|
|
8
|
+
export const OFFERED = new Set(MCCS.map(([mcc]) => mcc));
|
|
9
|
+
|
|
10
|
+
export type Form = Record<string, string>;
|
|
11
|
+
|
|
12
|
+
export type Kind = 'company' | 'individual';
|
|
13
|
+
|
|
14
|
+
export const has = (v: Form, k: string): boolean => (v[k] ?? '').trim() !== '';
|
|
15
|
+
|
|
16
|
+
export const dobPart = (v: Form, i: number): boolean => /^\d{4}-\d{2}-\d{2}$/.test(v.dob ?? '') && Number((v.dob ?? '').split('-')[i]) > 0;
|
|
17
|
+
|
|
18
|
+
/** Each requirement Stripe names, the form's answer that meets it, and which of the two sets it belongs to. */
|
|
19
|
+
export const REQUIREMENTS: Array<[string, (v: Form) => boolean, Kind[]]> = [
|
|
20
|
+
['business_profile.mcc', (v) => OFFERED.has((v.mcc ?? '').trim()), ['company', 'individual']],
|
|
21
|
+
['business_profile.url', (v) => has(v, 'url'), ['company', 'individual']],
|
|
22
|
+
['settings.payments.statement_descriptor', (v) => has(v, 'statement_descriptor'), ['company', 'individual']],
|
|
23
|
+
['company.name', (v) => has(v, 'company_name'), ['company']],
|
|
24
|
+
['company.tax_id', (v) => has(v, 'company_tax_id'), ['company']],
|
|
25
|
+
['company.phone', (v) => has(v, 'company_phone'), ['company']],
|
|
26
|
+
['company.address.line1', (v) => has(v, 'company_line1'), ['company']],
|
|
27
|
+
['company.address.city', (v) => has(v, 'company_city'), ['company']],
|
|
28
|
+
['company.address.state', (v) => has(v, 'company_state'), ['company']],
|
|
29
|
+
['company.address.postal_code', (v) => has(v, 'company_postal_code'), ['company']],
|
|
30
|
+
['company.owners_provided', (v) => v.owners_provided === 'provided', ['company']],
|
|
31
|
+
['owners.first_name', (v) => has(v, 'owner_first_name'), ['company']],
|
|
32
|
+
['owners.last_name', (v) => has(v, 'owner_last_name'), ['company']],
|
|
33
|
+
['owners.email', (v) => has(v, 'owner_email'), ['company']],
|
|
34
|
+
...(['first_name', 'last_name', 'email', 'phone'] as const).flatMap((f): Array<[string, (v: Form) => boolean, Kind[]]> => [[`representative.${f}`, (v) => has(v, f), ['company']], [`individual.${f}`, (v) => has(v, f), ['individual']]]),
|
|
35
|
+
...(['day', 'month', 'year'] as const).flatMap((f, i): Array<[string, (v: Form) => boolean, Kind[]]> => [[`representative.dob.${f}`, (v) => dobPart(v, 2 - i), ['company']], [`individual.dob.${f}`, (v) => dobPart(v, 2 - i), ['individual']]]),
|
|
36
|
+
...(['line1', 'city', 'state', 'postal_code'] as const).flatMap((f): Array<[string, (v: Form) => boolean, Kind[]]> => [[`representative.address.${f}`, (v) => has(v, f), ['company']], [`individual.address.${f}`, (v) => has(v, f), ['individual']]]),
|
|
37
|
+
['representative.relationship.title', (v) => has(v, 'title'), ['company']],
|
|
38
|
+
['representative.ssn_last_4', (v) => /^\d{4}$/.test(v.ssn_last_4 ?? ''), ['company']],
|
|
39
|
+
['individual.ssn_last_4', (v) => /^\d{4}$/.test(v.ssn_last_4 ?? ''), ['individual']],
|
|
40
|
+
['tos_acceptance.date', (v) => v.tos === 'accepted', ['company', 'individual']],
|
|
41
|
+
['tos_acceptance.ip', (v) => v.tos === 'accepted', ['company', 'individual']],
|
|
42
|
+
['external_account', (v) => has(v, 'routing_number') && has(v, 'account_number'), ['company', 'individual']],
|
|
43
|
+
];
|
|
44
|
+
|
|
45
|
+
/** The set an account onboards against: the two US sets the twin models, or none. */
|
|
46
|
+
export function kindOf(account: Row): Kind | undefined {
|
|
47
|
+
const type = account.business_type ?? 'individual';
|
|
48
|
+
return (account.country ?? 'US') === 'US' && (type === 'company' || type === 'individual') ? type : undefined;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/** What an account of this kind still owes, given the form's answers (none: all of it). */
|
|
52
|
+
export function currentlyDue(kind: Kind, v: Form = {}): string[] {
|
|
53
|
+
return REQUIREMENTS.filter(([, met, kinds]) => kinds.includes(kind) && !met(v)).map(([req]) => req);
|
|
54
|
+
}
|
|
@@ -9,17 +9,15 @@
|
|
|
9
9
|
// Where the evidence stops: the check knows only the served version's parameters (the spec's, surface.version). A
|
|
10
10
|
// request pinning an earlier version with Stripe-Version is not checked, since the pack holds no earlier spec, beyond
|
|
11
11
|
// the values of the payment_method_types it still takes (PAYMENT_METHOD_TYPES below); nested parameters are not checked.
|
|
12
|
-
|
|
13
|
-
import surface from '
|
|
14
|
-
import { manifest } from './manifest.ts';
|
|
15
|
-
import { SERVED_VERSION } from './stripe-version.ts';
|
|
12
|
+
|
|
13
|
+
import surface from '../generated/surface.gen.json' with { type: 'json' };
|
|
16
14
|
|
|
17
15
|
type Param = { name: string; required?: boolean };
|
|
18
16
|
type Op = { id: string; method: string; query?: Param[]; body?: Param[] };
|
|
19
|
-
const OPS = new Map((surface.operations as Op[]).map((o) => [o.id, o]));
|
|
17
|
+
export const OPS = new Map((surface.operations as Op[]).map((o) => [o.id, o]));
|
|
20
18
|
|
|
21
19
|
/** Parameters Stripe documents outside its published spec, each with the page that documents it. */
|
|
22
|
-
const DOCUMENTED: Record<string, string[]> = {
|
|
20
|
+
export const DOCUMENTED: Record<string, string[]> = {
|
|
23
21
|
// a top-up into the Issuing balance (docs.stripe.com/issuing/funding/balance: "destination_balance=issuing")
|
|
24
22
|
PostTopups: ['destination_balance'],
|
|
25
23
|
};
|
|
@@ -50,8 +48,8 @@ const DOCUMENTED: Record<string, string[]> = {
|
|
|
50
48
|
export const METHOD_TYPES_REMOVED_IN = '2026-08-26.preview';
|
|
51
49
|
/** Whether a pinned version is at or after the removal: versions order by their date (YYYY-MM-DD). */
|
|
52
50
|
export const methodTypesRemoved = (pinned: string): boolean => pinned.slice(0, 10) >= METHOD_TYPES_REMOVED_IN.slice(0, 10);
|
|
53
|
-
const REMOVED_TYPES = new Set(['PostPaymentIntents', 'PostPaymentIntentsIntent', 'PostPaymentIntentsIntentConfirm', 'PostSetupIntents', 'PostSetupIntentsIntent']);
|
|
54
|
-
const TYPED = new Set([...REMOVED_TYPES, 'PostCheckoutSessions']);
|
|
51
|
+
export const REMOVED_TYPES = new Set(['PostPaymentIntents', 'PostPaymentIntentsIntent', 'PostPaymentIntentsIntentConfirm', 'PostSetupIntents', 'PostSetupIntentsIntent']);
|
|
52
|
+
export const TYPED = new Set([...REMOVED_TYPES, 'PostCheckoutSessions']);
|
|
55
53
|
type Resource = { name: string; fields: Array<{ name: string; enum?: string[] }> };
|
|
56
54
|
/** The payment method types there are: the PaymentMethod object's `type` in the served spec. */
|
|
57
55
|
export const PAYMENT_METHOD_TYPES: readonly string[] = (surface.resources as Resource[]).find((r) => r.name === 'payment_method')?.fields.find((f) => f.name === 'type')?.enum ?? [];
|
|
@@ -61,56 +59,10 @@ export const PAYMENT_METHOD_TYPES: readonly string[] = (surface.resources as Res
|
|
|
61
59
|
* interac_present) and no `custom`. The surface keeps no request enums, so it is copied here. */
|
|
62
60
|
export const CHECKOUT_METHOD_TYPES: readonly string[] = ['acss_debit', 'affirm', 'afterpay_clearpay', 'alipay', 'alma', 'amazon_pay', 'au_becs_debit', 'bacs_debit', 'bancontact', 'billie', 'bizum', 'blik', 'boleto', 'card', 'cashapp', 'crypto', 'customer_balance', 'eps', 'fpx', 'giropay', 'grabpay', 'ideal', 'kakao_pay', 'klarna', 'konbini', 'kr_card', 'link', 'mb_way', 'mobilepay', 'multibanco', 'naver_pay', 'nz_bank_account', 'oxxo', 'p24', 'pay_by_bank', 'payco', 'paynow', 'paypal', 'paypay', 'payto', 'pix', 'promptpay', 'revolut_pay', 'samsung_pay', 'satispay', 'scalapay', 'sepa_debit', 'sequra', 'sofort', 'sunbit', 'swish', 'twint', 'upi', 'us_bank_account', 'wechat_pay', 'zip'];
|
|
63
61
|
/** The create page each intent's refusal links to. */
|
|
64
|
-
const TYPES_DOC: Record<string, string> = {
|
|
62
|
+
export const TYPES_DOC: Record<string, string> = {
|
|
65
63
|
payment_intents: 'https://stripe.com/docs/api/payment_intents/create#create_payment_intent-payment_method_types',
|
|
66
64
|
setup_intents: 'https://stripe.com/docs/api/setup_intents/create#create_setup_intent-payment_method_types',
|
|
67
65
|
};
|
|
68
66
|
|
|
69
67
|
/** An enum's values as Stripe lists them in a refusal: "a, b, or c". */
|
|
70
|
-
const oneOf = (values: readonly string[]): string => (values.length > 1 ? `${values.slice(0, -1).join(', ')}, or ${values.at(-1)}` : values.join(''));
|
|
71
|
-
|
|
72
|
-
/** An earlier version's payment_method_types refused: the first value that names no payment method type the
|
|
73
|
-
* operation takes, in the intent's words or (a Checkout Session) the enum's. */
|
|
74
|
-
function unknownMethodType(opId: string, given: unknown): Response | undefined {
|
|
75
|
-
const values = Array.isArray(given) ? given : given && typeof given === 'object' ? Object.values(given) : [given];
|
|
76
|
-
const checkout = opId === 'PostCheckoutSessions';
|
|
77
|
-
const known = checkout ? CHECKOUT_METHOD_TYPES : PAYMENT_METHOD_TYPES;
|
|
78
|
-
const i = values.findIndex((v) => !known.includes(String(v)));
|
|
79
|
-
if (i < 0) return undefined;
|
|
80
|
-
if (checkout) {
|
|
81
|
-
const param = `payment_method_types[${i}]`;
|
|
82
|
-
return vendorError(manifest, { status: 400, param, message: `Invalid ${param}: must be one of ${oneOf(known)}` });
|
|
83
|
-
}
|
|
84
|
-
const doc = TYPES_DOC[opId.startsWith('PostSetupIntents') ? 'setup_intents' : 'payment_intents'];
|
|
85
|
-
return vendorError(manifest, { status: 400, param: 'payment_method_types', message: `The payment method type "${String(values[i])}" is invalid. See ${doc} for the full list of supported payment method types.` });
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
/** payment_method_types refused where the caller's version removed it. */
|
|
89
|
-
const noLongerSupported = (version: string): Response =>
|
|
90
|
-
vendorError(manifest, { status: 400, code: 'payment_method_types_no_longer_supported', param: 'payment_method_types', message: `payment_method_types is no longer supported in API version ${version}. Use allowed_payment_method_types, or dynamic payment methods, instead.` });
|
|
91
|
-
|
|
92
|
-
/** Stripe's refusal of a request whose top-level parameters the operation does not take, or undefined. */
|
|
93
|
-
export async function refuseParameters(call: DerivedCall): Promise<Response | undefined> {
|
|
94
|
-
const op = OPS.get(call.operation.id);
|
|
95
|
-
if (!op) return undefined;
|
|
96
|
-
const pinned = call.request.headers.get('stripe-version');
|
|
97
|
-
if (pinned && pinned < SERVED_VERSION) {
|
|
98
|
-
if (!TYPED.has(op.id)) return undefined;
|
|
99
|
-
const earlier = await readParams(manifest, call.request.clone(), call.operation);
|
|
100
|
-
if (earlier.payment_method_types === undefined) return undefined;
|
|
101
|
-
if (REMOVED_TYPES.has(op.id) && methodTypesRemoved(pinned)) return noLongerSupported(pinned);
|
|
102
|
-
return unknownMethodType(op.id, earlier.payment_method_types);
|
|
103
|
-
}
|
|
104
|
-
const method = call.request.method.toUpperCase();
|
|
105
|
-
const known = new Set([...(op.query ?? []), ...(op.body ?? [])].map((p) => p.name).concat(DOCUMENTED[op.id] ?? []));
|
|
106
|
-
const params = await readParams(manifest, call.request.clone(), call.operation);
|
|
107
|
-
if (REMOVED_TYPES.has(op.id) && params.payment_method_types !== undefined) return noLongerSupported(pinned ?? SERVED_VERSION);
|
|
108
|
-
for (const name of Object.keys(params)) {
|
|
109
|
-
if (!known.has(name)) return vendorError(manifest, { status: 400, code: 'parameter_unknown', param: name, message: `Received unknown parameter: ${name}` });
|
|
110
|
-
}
|
|
111
|
-
const required = method === 'GET' || method === 'DELETE' ? (op.query ?? []) : (op.body ?? []);
|
|
112
|
-
for (const p of required) {
|
|
113
|
-
if (p.required && params[p.name] === undefined) return vendorError(manifest, { status: 400, code: 'parameter_missing', param: p.name, message: `Missing required param: ${p.name}.` });
|
|
114
|
-
}
|
|
115
|
-
return undefined;
|
|
116
|
-
}
|
|
68
|
+
export const oneOf = (values: readonly string[]): string => (values.length > 1 ? `${values.slice(0, -1).join(', ')}, or ${values.at(-1)}` : values.join(''));
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
// PaymentIntent semantics. The machine in ../manifest.ts says which moves of `status` are legal and
|
|
2
|
+
// what Stripe answers otherwise; these handlers compute what each move does. List, retrieve and
|
|
3
|
+
// update are the derived core's; search is Stripe's query language over the intents.
|
|
4
|
+
import type { Row } from './common.ts';
|
|
5
|
+
|
|
6
|
+
export const PI = 'payment_intent';
|
|
7
|
+
/** Bookkeeping: the intents whose caller named the methods (payment_method_types, allowed_payment_method_types) on
|
|
8
|
+
* create. The twin's default list (['card']) stands for Stripe's choice and restricts nothing, so only a named list
|
|
9
|
+
* refuses a confirm with a method of another type. Kept apart from the intent: a `_` subject is never pushed
|
|
10
|
+
* (world-core isTwinBookkeeping). */
|
|
11
|
+
export const TYPES_GIVEN = '_payment_intent_types_given';
|
|
12
|
+
|
|
13
|
+
// ── THE MONEY MODEL, continued: a succeeded intent has a Charge ──
|
|
14
|
+
//
|
|
15
|
+
// Real Stripe always materializes a Charge when a PaymentIntent succeeds and points the intent's
|
|
16
|
+
// `latest_charge` at it: the charge is what a refund lands on, so an intent that succeeds without
|
|
17
|
+
// one cannot answer "refund this payment" at all. Idempotent against a repeated confirm: an intent
|
|
18
|
+
// that already names a successful charge keeps it (a second one would double the money collected); a
|
|
19
|
+
// declined attempt's failed charge is history, and the payment that succeeds makes its own. The id is
|
|
20
|
+
// returned so the caller folds `latest_charge` into the same intent write (one write, one event). The
|
|
21
|
+
// charge is written as the event Stripe sends for it, `charge.succeeded` ("Occurs whenever a charge is
|
|
22
|
+
// successful", docs.stripe.com/api/events/types); Stripe has no `charge.created`.
|
|
23
|
+
/** What every charge an intent makes carries of it: its transfer_group, which "identifies the resulting payment as part
|
|
24
|
+
* of a group" (docs.stripe.com/api/payment_intents/object), its description and its metadata. */
|
|
25
|
+
export function intentCarries(pi: Row): Row {
|
|
26
|
+
return {
|
|
27
|
+
...(typeof pi.transfer_group === 'string' ? { transfer_group: pi.transfer_group } : {}),
|
|
28
|
+
...(typeof pi.description === 'string' ? { description: pi.description } : {}),
|
|
29
|
+
// "When a PaymentIntent creates a Charge, the metadata copies to the Charge in a one-time snapshot"
|
|
30
|
+
// (docs.stripe.com/metadata, "Copy metadata to another object")
|
|
31
|
+
...(pi.metadata && typeof pi.metadata === 'object' ? { metadata: { ...(pi.metadata as Row) } } : {}),
|
|
32
|
+
};
|
|
33
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
// Payment Link and Quote semantics. Both carry line items resolved from existing prices. A payment
|
|
2
|
+
// link is a reusable hosted-checkout URL, active until switched off; a quote moves draft → open
|
|
3
|
+
// (finalize) → accepted or canceled, the machine in ../manifest.ts. Link retrieve and update
|
|
4
|
+
// (`active`, its machine), quote retrieve and the quote list are the derived core's.
|
|
5
|
+
|
|
6
|
+
export const PL = 'payment_link';
|
|
@@ -0,0 +1,25 @@
|
|
|
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 { paymentMethodSubObject } from './stripe.ts';
|
|
4
|
+
import { AFTER_SUCCESS_CARDS } from './after-payment.ts';
|
|
5
|
+
import type { Row } from './common.ts';
|
|
6
|
+
|
|
7
|
+
export const PM = 'payment_method';
|
|
8
|
+
export const noBilling = { address: null, email: null, name: null, phone: null };
|
|
9
|
+
|
|
10
|
+
export const TEST_PM_CARDS: Record<string, { brand: string; number: string }> = {
|
|
11
|
+
...AFTER_SUCCESS_CARDS,
|
|
12
|
+
pm_card_mastercard: { brand: 'mastercard', number: '5555555555554444' },
|
|
13
|
+
pm_card_amex: { brand: 'amex', number: '378282246310005' },
|
|
14
|
+
pm_card_discover: { brand: 'discover', number: '6011111111111117' },
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
/** Attach a payment method to a customer (both known to exist or be attachable): a stored one moves to the
|
|
18
|
+
* customer; a test name mints a new PaymentMethod on the customer carrying that card's outcome. */
|
|
19
|
+
/** The card a test name (pm_card_*, tok_*) stands for, never stored as a PaymentMethod (docs.stripe.com/testing#cards). */
|
|
20
|
+
export function testCardOf(ref: string): Row | undefined {
|
|
21
|
+
const name = ref.replace(/^tok_/, 'pm_card_');
|
|
22
|
+
if (!name.startsWith('pm_card_')) return undefined;
|
|
23
|
+
const test = TEST_PM_CARDS[name] ?? { brand: 'visa', number: '4242424242424242' };
|
|
24
|
+
return { ...(paymentMethodSubObject('card', { card: { number: test.number } }).card as Row), brand: test.brand };
|
|
25
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
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.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 { Row } from './common.ts';
|
|
19
|
+
|
|
20
|
+
export const INTERVALS = new Set(['day', 'week', 'month', 'year']);
|
|
21
|
+
|
|
22
|
+
/** A recurring price in the plan object's shape (the create page's example response). */
|
|
23
|
+
export function planOf(price: Row): Row {
|
|
24
|
+
const r = (price.recurring ?? {}) as Row;
|
|
25
|
+
const amount = typeof price.unit_amount === 'number' ? price.unit_amount : null;
|
|
26
|
+
const decimal = typeof price.unit_amount_decimal === 'string' ? price.unit_amount_decimal : amount === null ? null : String(amount);
|
|
27
|
+
return {
|
|
28
|
+
id: price.id, object: 'plan', active: price.active ?? true, amount, amount_decimal: decimal,
|
|
29
|
+
billing_scheme: price.billing_scheme ?? 'per_unit', created: price.created, currency: price.currency, interval: r.interval ?? null,
|
|
30
|
+
interval_count: r.interval_count ?? 1, livemode: false, metadata: price.metadata ?? {}, meter: r.meter ?? null, nickname: price.nickname ?? null,
|
|
31
|
+
product: price.product, tiers_mode: price.tiers_mode ?? null, transform_usage: price.transform_quantity ?? null,
|
|
32
|
+
trial_period_days: r.trial_period_days ?? null, usage_type: r.usage_type ?? 'licensed',
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/** Metadata after an update: an empty value unsets the key, an empty `metadata` unsets them all. */
|
|
37
|
+
export function metadataAfter(was: Row, given: unknown): Row {
|
|
38
|
+
if (given === '' || given === null || typeof given !== 'object') return {};
|
|
39
|
+
const next: Row = { ...was };
|
|
40
|
+
for (const [k, v] of Object.entries(given as Row)) if (v === '' || v === null) delete next[k]; else next[k] = v;
|
|
41
|
+
return next;
|
|
42
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
// Handler 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 { Handler } from '@volter/world-core';
|
|
6
|
+
import type { Row } from './common.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
|
+
export 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
|
+
export 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
|
+
export 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
|
+
export 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
|
+
|
|
27
|
+
export const ORDER = 'climate.order';
|
|
28
|
+
|
|
29
|
+
// ── Financial Connections: a session is created for an account holder and its permissions; accounts
|
|
30
|
+
// are linked in the authentication flow Stripe.js opens (../screens/financial-connections.tsx) ──
|
|
31
|
+
|
|
32
|
+
export const FCS = 'financial_connections.session';
|
|
33
|
+
export const FCA = 'financial_connections.account';
|
|
34
|
+
export const FCT = 'financial_connections.transaction';
|
|
35
|
+
|
|
36
|
+
// ── Reporting: a representative subset of Stripe's report types; a run succeeds at once ──
|
|
37
|
+
|
|
38
|
+
export const REPORT_TYPES: Array<{ id: string; name: string }> = [
|
|
39
|
+
{ id: 'balance.summary.1', name: 'Balance summary' },
|
|
40
|
+
{ id: 'balance_change_from_activity.summary.1', name: 'Balance change from activity (summary)' },
|
|
41
|
+
{ id: 'payouts.summary.1', name: 'Payouts (summary)' },
|
|
42
|
+
{ id: 'payout_reconciliation.by_id.itemized.4', name: 'Payout reconciliation (itemized)' },
|
|
43
|
+
];
|
|
44
|
+
export const reportTypeView = (t: { id: string; name: string }): Row => ({
|
|
45
|
+
id: t.id, object: 'reporting.report_type', name: t.name, version: 1,
|
|
46
|
+
data_available_start: 0, data_available_end: 0, default_columns: null, updated: 0, livemode: false,
|
|
47
|
+
});
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
// Radar semantics: reviews of payments Radar held (approving closes one, the machine in
|
|
2
|
+
// ../manifest.ts) and the value lists custom rules reference, with their items. Review list and
|
|
3
|
+
// retrieve, value-list list and retrieve, and value-list-item retrieve are the derived core's.
|
|
4
|
+
|
|
5
|
+
export const VL = 'radar.value_list';
|
|
6
|
+
export const VLI = 'radar.value_list_item';
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
// Refund semantics. A refund always names what it took money out of and lands there: a refund
|
|
2
|
+
// naming nothing, an id nobody minted, or more than the charge has left is refused as Stripe
|
|
3
|
+
// refuses it. The machine in ../manifest.ts says only a refund waiting on the customer
|
|
4
|
+
// (requires_action) may be canceled. List and update are the derived core's.
|
|
5
|
+
//
|
|
6
|
+
// Refunding a destination charge can take back the connected account's share (reverse_transfer: a reversal of the
|
|
7
|
+
// charge's transfer, in proportion to the refund) and the platform's (refund_application_fee: a refund of the
|
|
8
|
+
// application fee, in proportion) (docs.stripe.com/api/refunds/create#create_refund-reverse_transfer,
|
|
9
|
+
// docs.stripe.com/connect/destination-charges#issue-refunds). Where the documentation stops and the twin decides: the
|
|
10
|
+
// twin's destination charge transfers the amount less the fee (the fee is kept back rather than collected from the
|
|
11
|
+
// connected account), so a fee refund moves no money of its own; the reversal and the refund settle both shares.
|
|
12
|
+
//
|
|
13
|
+
// A payment made by bank transfer (from the customer's cash balance) is refunded to the customer's bank account: Stripe
|
|
14
|
+
// emails the customer (instructions_email, else the customer's email) for their bank details and the refund waits in
|
|
15
|
+
// requires_action, moving no money, until they answer; only then can it still be canceled. With origin=customer_balance
|
|
16
|
+
// it goes back to the cash balance at once (docs.stripe.com/payments/customer-balance/refunding,
|
|
17
|
+
// docs.stripe.com/api/refunds/cancel). Where the documentation stops and the twin decides: the customer never answers
|
|
18
|
+
// the email in the World, and its link expires 30 days on.
|
|
19
|
+
//
|
|
20
|
+
// An uncaptured charge holds an authorization, not money. A PaymentIntent's is not refunded: "the charge attached to the
|
|
21
|
+
// PaymentIntent remains uncaptured and can't be refunded directly. You must cancel the PaymentIntent"
|
|
22
|
+
// (docs.stripe.com/refunds), which releases it (charges.ts cancelAuthorization). A charge made with capture=false is
|
|
23
|
+
// released by its refund, as its authorization would be "automatically refunded if uncaptured" (spec/openapi.json.gz,
|
|
24
|
+
// `capture_before`): refunded in full, no balance moved, and its capture refused afterwards. Where the documentation
|
|
25
|
+
// stops and the twin decides: the refusal's code (payment_intent_unexpected_state) and wording, and that a refund of a
|
|
26
|
+
// capture=false charge releases the whole authorization, so an `amount` short of it is refused.
|
|
27
|
+
|
|
28
|
+
// the reasons a caller may give; `expired_uncaptured_charge` is Stripe's own
|
|
29
|
+
export const REFUND_REASONS = new Set(['duplicate', 'fraudulent', 'requested_by_customer']);
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
// A subscription's invoices over time: the first one Checkout pays, and each renewal. Time's moves are made
|
|
2
|
+
// as the twin's trial end already made them: caught up to the customer's clock (the World's, or its test
|
|
3
|
+
// clock) whenever the twin is asked anything (./front.ts), each checked against the machines in
|
|
4
|
+
// ../manifest.ts.
|
|
5
|
+
//
|
|
6
|
+
// - Checkout's subscription session pays the first invoice with the card the customer entered, which becomes the
|
|
7
|
+
// subscription's default payment method (docs.stripe.com/payments/checkout/how-checkout-works); nothing is due
|
|
8
|
+
// on a trial's.
|
|
9
|
+
// - At each period's end Stripe drafts a `subscription_cycle` invoice for the next period and advances the
|
|
10
|
+
// period; a trial's end is the first such renewal, and the subscription is active from then
|
|
11
|
+
// (docs.stripe.com/billing/subscriptions/overview#how-payments-work-subscriptions,
|
|
12
|
+
// docs.stripe.com/billing/subscriptions/trials).
|
|
13
|
+
// - About an hour after, Stripe finalizes the draft and charges the subscription's default payment method,
|
|
14
|
+
// else the customer's (docs.stripe.com/invoicing/integration/workflow-transitions#finalized,
|
|
15
|
+
// docs.stripe.com/api/subscriptions/object#subscription_object-default_payment_method).
|
|
16
|
+
// - A declined renewal leaves the invoice open with its attempt counted and the subscription past_due
|
|
17
|
+
// (docs.stripe.com/billing/subscriptions/overview#payment-status); paying the invoice later, through the API
|
|
18
|
+
// (docs.stripe.com/api/invoices/pay) or on the customer portal (docs.stripe.com/customer-management), makes it
|
|
19
|
+
// active again.
|
|
20
|
+
//
|
|
21
|
+
// Where the documentation stops and the twin decides: Stripe retries a failed renewal on its Smart Retries
|
|
22
|
+
// schedule and may then cancel or mark the subscription unpaid; the twin makes no retry (next_payment_attempt
|
|
23
|
+
// is null) and leaves it past_due until the invoice is paid. A paused subscription (pause_collection) is not renewed.
|
|
24
|
+
// - One set to cancel at its period's end is canceled when the period ends, with no renewal
|
|
25
|
+
// (docs.stripe.com/billing/subscriptions/cancel#cancel-at-end-of-cycle).
|
|
26
|
+
import { priceAmount } from './stripe.ts';
|
|
27
|
+
import type { Row } from './common.ts';
|
|
28
|
+
|
|
29
|
+
export const SUB = 'subscription';
|
|
30
|
+
export const INV = 'invoice';
|
|
31
|
+
export const HOUR = 3600;
|
|
32
|
+
/** The statuses a subscription renews in. */
|
|
33
|
+
export const RENEWING = ['trialing', 'active', 'past_due'];
|
|
34
|
+
|
|
35
|
+
export const itemsOf = (sub: Row): Row[] => ((sub.items as { data?: Row[] } | undefined)?.data) ?? [];
|
|
36
|
+
|
|
37
|
+
/** An item's quantity as it bills: 1 when none is set, and 0 when 0 is (a quantity of 0 bills nothing). */
|
|
38
|
+
export function itemQuantity(it: Row): number {
|
|
39
|
+
return it.quantity === undefined || it.quantity === null ? 1 : Math.max(0, Math.trunc(Number(it.quantity) || 0));
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/** The subscription's discounts with a `once` coupon's spent: "When a subscription uses a coupon with `duration=once`, the
|
|
43
|
+
* coupon is considered used after the invoice finalizes and is removed from the subscription's `discounts` array"
|
|
44
|
+
* (docs.stripe.com/billing/subscriptions/coupons#coupon-duration). */
|
|
45
|
+
export function unspentDiscounts(discounts: unknown): Row[] {
|
|
46
|
+
return ((discounts as Row[] | undefined) ?? []).filter((d) => !(d && typeof d === 'object' && (d.coupon as Row | undefined)?.duration === 'once'));
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/** The coupon ids an invoice's discounts name. */
|
|
50
|
+
export const couponsOf = (discounts: unknown): Set<string> => new Set(((discounts as Row[] | undefined) ?? []).map((d) => {
|
|
51
|
+
const c = d && typeof d === 'object' ? d.coupon : undefined;
|
|
52
|
+
return typeof c === 'string' ? c : c && typeof c === 'object' ? String((c as Row).id ?? '') : '';
|
|
53
|
+
}).filter(Boolean));
|
|
54
|
+
|
|
55
|
+
/** A subscription's discounts after `invoice` finalizes: less the `once` coupons it took. */
|
|
56
|
+
export function keptAfter(discounts: Row[], invoice: Row): Row[] {
|
|
57
|
+
const taken = couponsOf(invoice.discounts);
|
|
58
|
+
return discounts.filter((d) => !(unspentDiscounts([d]).length === 0 && [...couponsOf([d])].some((c) => taken.has(c))));
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/** A Checkout session's one-time line items as lines of its subscription's first invoice, numbered after its `after` lines. */
|
|
62
|
+
export function oneTimeLines(invoiceId: string, sub: Row, items: Row[], after: number, at: number, currency: string) {
|
|
63
|
+
return items.map((it, i) => {
|
|
64
|
+
const price = it.price && typeof it.price === 'object' ? (it.price as Row) : null;
|
|
65
|
+
const quantity = itemQuantity(it);
|
|
66
|
+
return {
|
|
67
|
+
id: `il_twin_${invoiceId}_${after + i + 1}`, object: 'line_item', type: 'subscription',
|
|
68
|
+
amount: priceAmount(price ?? undefined, quantity), currency, quantity, proration: false,
|
|
69
|
+
price, subscription: sub.id, subscription_item: null, invoice_item: null,
|
|
70
|
+
period: { start: at, end: at }, description: typeof it.description === 'string' ? it.description : null,
|
|
71
|
+
};
|
|
72
|
+
});
|
|
73
|
+
}
|