@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.
- 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
|
@@ -1,37 +1,12 @@
|
|
|
1
|
-
//
|
|
2
|
-
//
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
// are already available by the World's clock is no exception, and the transfer is held to the available balance as any
|
|
11
|
-
// other. "The amount of the transfer must not exceed the amount of the source charge", several transfers may share one
|
|
12
|
-
// charge while "the sum of the transfers doesn't exceed the source charge", and the charge's balance currency must
|
|
13
|
-
// match. "If the source charge has a `transfer_group` value, Stripe assigns the same value to the transfer's
|
|
14
|
-
// `transfer_group`. If it doesn't, then Stripe generates a string in the format `group_` plus the associated
|
|
15
|
-
// PaymentIntent ID ... It assigns that string as the `transfer_group` for both the charge and the transfer."
|
|
16
|
-
// Where the documentation stops and the twin decides: the sum from one charge counts each transfer less what was
|
|
17
|
-
// reversed of it; a transfer_group the request names is kept only when the charge has none and no PaymentIntent to
|
|
18
|
-
// name one after; an uncaptured charge (an authorization, docs silent) is refused as a source_transaction until it is
|
|
19
|
-
// captured; the refusals' wording is the twin's.
|
|
20
|
-
// Transfer list, retrieve and update and application-fee list and retrieve are the derived core's.
|
|
21
|
-
import type { Semantics, SemanticsContext } from '@volter/world-core';
|
|
22
|
-
import { validateMoney } from '../stripe-twin.ts';
|
|
23
|
-
import { refusePayout, settleTransfer, settleTransferReversal } from './ledger.ts';
|
|
24
|
-
import { at, created, fail, list, newest, send, type Row } from './shared.ts';
|
|
25
|
-
|
|
26
|
-
const transferMissing = (ctx: SemanticsContext, id: string): Response => fail(ctx, `No such transfer: '${id}'`, 404, 'resource_missing');
|
|
27
|
-
const emptyList = (url: string): Row => ({ object: 'list', data: [], has_more: false, total_count: 0, url });
|
|
28
|
-
|
|
29
|
-
/** A transfer to an account whose transfers capability is not active. */
|
|
30
|
-
function transfersInactive(ctx: SemanticsContext): Response {
|
|
31
|
-
return ctx.refuse({ status: 400, code: 'insufficient_capabilities_for_transfer', param: 'destination', message: 'Your destination account needs to have at least one of the following capabilities enabled: transfers, crypto_transfers, legacy_payments' });
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
const create: Semantics = async (ctx) => {
|
|
1
|
+
// Stripe's transfers operations (docs/contributing/architecture.md, "What an author writes"): each handler over the
|
|
2
|
+
// handler contract's context, computing with the engine (../engine/).
|
|
3
|
+
import type { HandlerContext } from '@volter/world-core';
|
|
4
|
+
import type { Row } from '../engine/common.ts';
|
|
5
|
+
import { nowUnix, validateMoney } from '../engine/stripe.ts';
|
|
6
|
+
import { emptyList } from '../engine/transfers.ts';
|
|
7
|
+
import { at, created, fail, giveBack, list, newest, refusePayout, send, settledSourceRefused, settleTransfer, settleTransferReversal, transferMissing, transfersInactive } from './shared.ts';
|
|
8
|
+
|
|
9
|
+
export async function PostTransfers(ctx: HandlerContext): Promise<Response> {
|
|
35
10
|
const bad = validateMoney(ctx.params);
|
|
36
11
|
if (bad) return send(ctx, bad);
|
|
37
12
|
const destination = typeof ctx.params.destination === 'string' ? ctx.params.destination : '';
|
|
@@ -55,9 +30,9 @@ const create: Semantics = async (ctx) => {
|
|
|
55
30
|
if (already + amount > Number(charge.amount ?? 0)) return fail(ctx, `The transfers from source_transaction ${sourceId} would exceed its amount (${String(charge.amount)}).`, 400, 'invalid_request_error');
|
|
56
31
|
const bt = typeof charge.balance_transaction === 'string' ? ctx.get('balance_transaction', charge.balance_transaction) : undefined;
|
|
57
32
|
// a charge that has settled waives nothing: the transfer comes out of what is available
|
|
58
|
-
const settledRefusal = bt && Number(bt.available_on) <= Number(ctx.
|
|
33
|
+
const settledRefusal = bt && Number(bt.available_on) <= Number(nowUnix(ctx.occurredAt)) ? settledSourceRefused(ctx, amount, currency) : undefined;
|
|
59
34
|
if (settledRefusal) return settledRefusal;
|
|
60
|
-
availableOn = Math.max(Number(ctx.
|
|
35
|
+
availableOn = Math.max(Number(nowUnix(ctx.occurredAt)), Number(bt?.available_on) || 0);
|
|
61
36
|
group = typeof charge.transfer_group === 'string' ? charge.transfer_group : typeof charge.payment_intent === 'string' ? `group_${charge.payment_intent}` : undefined;
|
|
62
37
|
// the generated group is the charge's too
|
|
63
38
|
if (group && charge.transfer_group !== group) await ctx.write('charge', sourceId, { transfer_group: group }, 'charge.transfer_group_assigned');
|
|
@@ -75,100 +50,5 @@ const create: Semantics = async (ctx) => {
|
|
|
75
50
|
destination_payment: `py_${id.replace(/^tr_/, '')}`,
|
|
76
51
|
}),
|
|
77
52
|
);
|
|
78
|
-
};
|
|
79
|
-
|
|
80
|
-
/** A transfer from a charge whose funds have settled: "With a source_transaction, the transfer request returns success
|
|
81
|
-
* regardless of your available balance if the related charge hasn't settled yet" (docs.stripe.com/connect/separate-
|
|
82
|
-
* charges-and-transfers), so a settled one comes out of the available balance. */
|
|
83
|
-
function settledSourceRefused(ctx: SemanticsContext, amount: number, currency: string): Response | undefined {
|
|
84
|
-
return refusePayout(ctx, amount, currency, undefined);
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
/** An application fee refunded to its whole through its own refunds endpoint: the fee machine's move, or its refusal. */
|
|
88
|
-
function feeFullyRefunded(ctx: SemanticsContext, resource: string, flag: string, id: string): Response | undefined {
|
|
89
|
-
const refused = ctx.legal(resource, flag, ctx.call.operation.id, 'false', 'true', id);
|
|
90
|
-
return refused ? ctx.refuse(refused) : undefined;
|
|
91
53
|
}
|
|
92
54
|
|
|
93
|
-
/** Take `amount` (the remainder by default) back out of a parent's total, as a child row appended to its list. */
|
|
94
|
-
async function giveBack(ctx: SemanticsContext, o: {
|
|
95
|
-
parent: Row; parentResource: string; child: string; childFields: (amount: number) => Row; childDefaults: Row;
|
|
96
|
-
doneField: string; flag: string; listUrl: string; op: string; tooLarge: (remaining: number) => string;
|
|
97
|
-
/** what the money movement itself writes, once the child exists */
|
|
98
|
-
settle?: (child: Row, amount: number) => Promise<void>;
|
|
99
|
-
}): Promise<Response> {
|
|
100
|
-
const id = String(o.parent.id);
|
|
101
|
-
const total = Number(o.parent.amount ?? 0);
|
|
102
|
-
const already = Number(o.parent[o.doneField] ?? 0);
|
|
103
|
-
const remaining = total - already;
|
|
104
|
-
const amount = ctx.params.amount !== undefined ? Math.trunc(Number(ctx.params.amount) || 0) : remaining;
|
|
105
|
-
if (amount <= 0 || amount > remaining) return fail(ctx, o.tooLarge(remaining), 400, 'amount_too_large');
|
|
106
|
-
const done = already + amount;
|
|
107
|
-
// a fee refunded in full is `refunded`: the application fee machine's move (a transfer's `reversed` is no state)
|
|
108
|
-
const feeRefusal = o.parentResource === 'application_fee' && done >= total && o.parent[o.flag] !== true ? feeFullyRefunded(ctx, o.parentResource, o.flag, id) : undefined;
|
|
109
|
-
if (feeRefusal) return feeRefusal;
|
|
110
|
-
// the `metadata` a reversal or a fee refund is created with is its own ("Set of key-value pairs that you can attach to
|
|
111
|
-
// an object", docs.stripe.com/api/transfer_reversals/create, docs.stripe.com/api/fee_refunds/create)
|
|
112
|
-
const metadata = ctx.params.metadata && typeof ctx.params.metadata === 'object' ? { metadata: ctx.params.metadata } : {};
|
|
113
|
-
const child = await created(ctx, o.child, { ...o.childFields(amount), ...metadata }, o.childDefaults);
|
|
114
|
-
if (o.settle) await o.settle(child, amount);
|
|
115
|
-
const existing = (o.parent[o.flag === 'reversed' ? 'reversals' : 'refunds'] as Row) ?? { object: 'list', data: [], has_more: false, total_count: 0 };
|
|
116
|
-
const data = [...((existing.data as unknown[]) ?? []), child];
|
|
117
|
-
await ctx.write(o.parentResource, id, {
|
|
118
|
-
[o.doneField]: done, [o.flag]: done >= total,
|
|
119
|
-
[o.flag === 'reversed' ? 'reversals' : 'refunds']: { ...existing, data, total_count: data.length, url: o.listUrl },
|
|
120
|
-
}, o.op);
|
|
121
|
-
return ctx.reply(child);
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
const reverse: Semantics = async (ctx) => {
|
|
125
|
-
const id = at(ctx, 'id');
|
|
126
|
-
const tr = ctx.get('transfer', id);
|
|
127
|
-
if (!tr) return transferMissing(ctx, id);
|
|
128
|
-
return giveBack(ctx, {
|
|
129
|
-
parent: tr, parentResource: 'transfer', child: 'transfer_reversal',
|
|
130
|
-
childFields: (amount) => ({ amount, currency: tr.currency ?? 'usd', transfer: id }),
|
|
131
|
-
childDefaults: { balance_transaction: null, destination_payment_refund: null, source_refund: null, metadata: {} },
|
|
132
|
-
doneField: 'amount_reversed', flag: 'reversed', listUrl: `/v1/transfers/${id}/reversals`, op: 'transfer.reversed',
|
|
133
|
-
tooLarge: (remaining) => `Transfer ${id} can only be reversed up to ${remaining}.`,
|
|
134
|
-
settle: async (child, amount) => {
|
|
135
|
-
const bt = await settleTransferReversal(ctx, String(child.id), amount, String(tr.currency ?? 'usd'), String(tr.destination));
|
|
136
|
-
await ctx.write('transfer_reversal', String(child.id), { balance_transaction: bt }, 'transfer_reversal.updated');
|
|
137
|
-
},
|
|
138
|
-
});
|
|
139
|
-
};
|
|
140
|
-
|
|
141
|
-
const reversals: Semantics = async (ctx) => {
|
|
142
|
-
const id = at(ctx, 'id');
|
|
143
|
-
if (!ctx.get('transfer', id)) return transferMissing(ctx, id);
|
|
144
|
-
return list(ctx, 'transfer_reversal', newest(ctx, 'transfer_reversal').filter((r) => r.transfer === id));
|
|
145
|
-
};
|
|
146
|
-
|
|
147
|
-
const feeMissing = (ctx: SemanticsContext, id: string): Response => fail(ctx, `No such application fee: '${id}'`, 404, 'resource_missing');
|
|
148
|
-
|
|
149
|
-
const refundFee: Semantics = async (ctx) => {
|
|
150
|
-
const id = at(ctx, 'id');
|
|
151
|
-
const fee = ctx.get('application_fee', id);
|
|
152
|
-
if (!fee) return feeMissing(ctx, id);
|
|
153
|
-
return giveBack(ctx, {
|
|
154
|
-
parent: fee, parentResource: 'application_fee', child: 'fee_refund',
|
|
155
|
-
childFields: (amount) => ({ amount, currency: fee.currency ?? 'usd', fee: id }),
|
|
156
|
-
childDefaults: { balance_transaction: null, metadata: {} },
|
|
157
|
-
doneField: 'amount_refunded', flag: 'refunded', listUrl: `/v1/application_fees/${id}/refunds`, op: 'application_fee.refunded',
|
|
158
|
-
tooLarge: (remaining) => `Application fee ${id} can only be refunded up to ${remaining}.`,
|
|
159
|
-
});
|
|
160
|
-
};
|
|
161
|
-
|
|
162
|
-
const feeRefunds: Semantics = async (ctx) => {
|
|
163
|
-
const id = at(ctx, 'id');
|
|
164
|
-
if (!ctx.get('application_fee', id)) return feeMissing(ctx, id);
|
|
165
|
-
return list(ctx, 'fee_refund', newest(ctx, 'fee_refund').filter((r) => r.fee === id));
|
|
166
|
-
};
|
|
167
|
-
|
|
168
|
-
export const transfers: Record<string, Semantics> = {
|
|
169
|
-
PostTransfers: create,
|
|
170
|
-
PostTransfersIdReversals: reverse,
|
|
171
|
-
GetTransfersIdReversals: reversals,
|
|
172
|
-
PostApplicationFeesIdRefunds: refundFee,
|
|
173
|
-
GetApplicationFeesIdRefunds: feeRefunds,
|
|
174
|
-
};
|
package/src/server.ts
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
// FETCH-FIRST (runtime contract R12b): a fixed file, the kernel's serve seam around the pack's fetch (./fetch.ts).
|
|
2
|
+
import { serveHttp, type PackFetchOptions } from '@volter/world-core';
|
|
3
|
+
import { createStripeFetch } from './fetch.ts';
|
|
4
|
+
|
|
5
|
+
export async function createStripeTwinServer(options: PackFetchOptions & { port?: number } = {}): Promise<{ port: number; stop: () => void }> {
|
|
6
|
+
const server = await serveHttp({ port: options.port ?? 0, idleTimeout: 60, fetch: createStripeFetch(options) });
|
|
7
|
+
return { port: server.port ?? options.port ?? 0, stop: () => server.stop(true) };
|
|
8
|
+
}
|
package/client/dashboard-api.ts
DELETED
|
@@ -1,286 +0,0 @@
|
|
|
1
|
-
// The Stripe Dashboard's reads and writes, through Stripe's own API on this origin (docs/contributing/
|
|
2
|
-
// architecture.md, "Screens": a workspace reads and writes only through the pack's operations). The calls
|
|
3
|
-
// the Dashboard makes for the pages it shows: the balance, payments (PaymentIntents and the Charges they
|
|
4
|
-
// made), refunds, customers and their saved payment methods, subscriptions, invoices, products and prices,
|
|
5
|
-
// and events for a detail page's timeline. The writes a person makes here: refund a payment
|
|
6
|
-
// (POST /v1/refunds), cancel a subscription (DELETE /v1/subscriptions/{id}, or schedule it with
|
|
7
|
-
// cancel_at_period_end), create a customer or a product. Bodies are form-encoded as Stripe's API takes them;
|
|
8
|
-
// an `error` envelope, never the HTTP status alone, is what refuses.
|
|
9
|
-
|
|
10
|
-
type Json = any;
|
|
11
|
-
export type StripeObject = Record<string, any>;
|
|
12
|
-
|
|
13
|
-
export function wireBaseFrom(hasBaseElement: boolean, baseURI: string): string {
|
|
14
|
-
return hasBaseElement ? new URL('.', baseURI).pathname.replace(/\/$/, '') : '';
|
|
15
|
-
}
|
|
16
|
-
// Served at the origin root the base is ''; served under a path prefix (an embedder's earlier <base>) every
|
|
17
|
-
// call resolves inside that prefix.
|
|
18
|
-
export const API_BASE = typeof document === 'undefined' ? '' : wireBaseFrom(document.querySelector('base[href]') !== null, document.baseURI);
|
|
19
|
-
|
|
20
|
-
export class StripeApiError extends Error {
|
|
21
|
-
constructor(message: string, readonly code?: string) { super(message); }
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
async function call(method: string, path: string, body?: Record<string, string | number | boolean | undefined>): Promise<Json> {
|
|
25
|
-
const init: RequestInit = { method, headers: { accept: 'application/json' } };
|
|
26
|
-
if (body) {
|
|
27
|
-
const form = Object.entries(body).filter(([, v]) => v !== undefined && v !== '').map(([k, v]) => `${encodeURIComponent(k)}=${encodeURIComponent(String(v))}`).join('&');
|
|
28
|
-
init.body = form;
|
|
29
|
-
(init.headers as Record<string, string>)['content-type'] = 'application/x-www-form-urlencoded';
|
|
30
|
-
}
|
|
31
|
-
const res = await fetch(`${API_BASE}${path}`, init);
|
|
32
|
-
const json = await res.json().catch(() => ({ error: { message: `${res.status} ${res.statusText}` } }));
|
|
33
|
-
if (json && json.error) throw new StripeApiError(String(json.error.message ?? 'Request failed'), json.error.code);
|
|
34
|
-
return json;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
export const retrieve = (path: string): Promise<StripeObject> => call('GET', path);
|
|
38
|
-
/** A list endpoint's `data`, newest first as Stripe returns it (one page of up to 100). */
|
|
39
|
-
export async function list(path: string): Promise<StripeObject[]> {
|
|
40
|
-
const sep = path.includes('?') ? '&' : '?';
|
|
41
|
-
const body = await call('GET', `${path}${sep}limit=100`);
|
|
42
|
-
return Array.isArray(body?.data) ? body.data : [];
|
|
43
|
-
}
|
|
44
|
-
const optional = <T>(p: Promise<T>, fallback: T): Promise<T> => p.catch(() => fallback);
|
|
45
|
-
|
|
46
|
-
// ── what a payment row is ────────────────────────────────────────────────────
|
|
47
|
-
/** One row of the Payments list: a PaymentIntent (or a Charge made without one) with what the Dashboard
|
|
48
|
-
* shows beside it — its charge, refunds, card and customer. */
|
|
49
|
-
export type Payment = {
|
|
50
|
-
id: string;
|
|
51
|
-
amount: number;
|
|
52
|
-
currency: string;
|
|
53
|
-
status: PaymentStatus;
|
|
54
|
-
description?: string;
|
|
55
|
-
created: number;
|
|
56
|
-
customer?: StripeObject;
|
|
57
|
-
charge?: StripeObject;
|
|
58
|
-
intent?: StripeObject;
|
|
59
|
-
paymentMethod?: StripeObject;
|
|
60
|
-
amountRefunded: number;
|
|
61
|
-
refundedAt?: number;
|
|
62
|
-
declineReason?: string;
|
|
63
|
-
declineMessage?: string;
|
|
64
|
-
};
|
|
65
|
-
export type PaymentStatus = 'succeeded' | 'refunded' | 'partially_refunded' | 'failed' | 'incomplete' | 'uncaptured' | 'canceled' | 'disputed' | 'processing';
|
|
66
|
-
|
|
67
|
-
export function paymentStatusOf(intent: StripeObject | undefined, charge: StripeObject | undefined): PaymentStatus {
|
|
68
|
-
if (charge?.disputed) return 'disputed';
|
|
69
|
-
if (charge?.refunded) return 'refunded';
|
|
70
|
-
if (charge && Number(charge.amount_refunded) > 0) return 'partially_refunded';
|
|
71
|
-
if (charge?.status === 'failed') return 'failed';
|
|
72
|
-
if (intent) {
|
|
73
|
-
if (intent.status === 'succeeded') return 'succeeded';
|
|
74
|
-
if (intent.status === 'canceled') return 'canceled';
|
|
75
|
-
if (intent.status === 'requires_capture') return 'uncaptured';
|
|
76
|
-
if (intent.status === 'processing') return 'processing';
|
|
77
|
-
if (intent.last_payment_error) return 'failed';
|
|
78
|
-
return 'incomplete';
|
|
79
|
-
}
|
|
80
|
-
return charge?.status === 'succeeded' ? 'succeeded' : charge?.status === 'pending' ? 'processing' : 'failed';
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
const DECLINE_REASONS: Record<string, string> = {
|
|
84
|
-
generic_decline: 'Generic decline', insufficient_funds: 'Insufficient funds', lost_card: 'Lost card', stolen_card: 'Stolen card',
|
|
85
|
-
expired_card: 'Expired card', incorrect_cvc: 'Incorrect CVC', processing_error: 'Processing error', card_declined: 'Card declined',
|
|
86
|
-
};
|
|
87
|
-
export const declineReasonText = (code: string | undefined): string | undefined => (code ? DECLINE_REASONS[code] ?? code.replace(/_/g, ' ') : undefined);
|
|
88
|
-
|
|
89
|
-
type Directory = { customers: Map<string, StripeObject>; paymentMethods: Map<string, StripeObject> };
|
|
90
|
-
|
|
91
|
-
async function paymentMethodsById(ids: Iterable<string>): Promise<Map<string, StripeObject>> {
|
|
92
|
-
const unique = [...new Set([...ids].filter((id) => typeof id === 'string' && id.startsWith('pm_')))];
|
|
93
|
-
const found = await Promise.all(unique.map((id) => optional(retrieve(`/v1/payment_methods/${id}`), undefined as StripeObject | undefined)));
|
|
94
|
-
return new Map(found.filter((pm): pm is StripeObject => Boolean(pm?.id)).map((pm) => [pm.id, pm]));
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
function paymentOf(intent: StripeObject | undefined, charge: StripeObject | undefined, refunds: StripeObject[], dir: Directory): Payment {
|
|
98
|
-
const base = intent ?? charge!;
|
|
99
|
-
const customerId = typeof base.customer === 'string' ? base.customer : base.customer?.id;
|
|
100
|
-
const pmId = typeof base.payment_method === 'string' ? base.payment_method : charge?.payment_method;
|
|
101
|
-
const error = intent?.last_payment_error;
|
|
102
|
-
const refundsOf = refunds.filter((r) => (intent && r.payment_intent === intent.id) || (charge && r.charge === charge.id));
|
|
103
|
-
return {
|
|
104
|
-
id: String(base.id),
|
|
105
|
-
amount: Number(base.amount) || 0,
|
|
106
|
-
currency: String(base.currency ?? 'usd'),
|
|
107
|
-
status: paymentStatusOf(intent, charge),
|
|
108
|
-
description: base.description ?? charge?.description ?? undefined,
|
|
109
|
-
created: Number(base.created) || 0,
|
|
110
|
-
customer: customerId ? dir.customers.get(customerId) ?? { id: customerId } : undefined,
|
|
111
|
-
charge, intent,
|
|
112
|
-
paymentMethod: pmId ? dir.paymentMethods.get(pmId) : undefined,
|
|
113
|
-
amountRefunded: Number(charge?.amount_refunded) || refundsOf.reduce((n, r) => n + (r.status === 'failed' ? 0 : Number(r.amount) || 0), 0),
|
|
114
|
-
refundedAt: refundsOf.length ? Math.max(...refundsOf.map((r) => Number(r.created) || 0)) : undefined,
|
|
115
|
-
declineReason: declineReasonText(error?.decline_code ?? error?.code ?? charge?.failure_code),
|
|
116
|
-
declineMessage: error?.message ?? charge?.failure_message ?? undefined,
|
|
117
|
-
};
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
/** The Payments list: every PaymentIntent, and every Charge made without one. */
|
|
121
|
-
export async function loadPayments(): Promise<Payment[]> {
|
|
122
|
-
const [intents, charges, refunds, customers] = await Promise.all([
|
|
123
|
-
list('/v1/payment_intents'), list('/v1/charges'), optional(list('/v1/refunds'), []), list('/v1/customers'),
|
|
124
|
-
]);
|
|
125
|
-
const chargeById = new Map(charges.map((c) => [c.id, c]));
|
|
126
|
-
const pmIds = [...intents.map((i) => i.payment_method), ...charges.map((c) => c.payment_method)];
|
|
127
|
-
const dir: Directory = { customers: new Map(customers.map((c) => [c.id, c])), paymentMethods: await paymentMethodsById(pmIds) };
|
|
128
|
-
const rows = intents.map((pi) => {
|
|
129
|
-
const charge = (typeof pi.latest_charge === 'string' ? chargeById.get(pi.latest_charge) : pi.latest_charge) ?? charges.find((c) => c.payment_intent === pi.id);
|
|
130
|
-
return paymentOf(pi, charge, refunds, dir);
|
|
131
|
-
});
|
|
132
|
-
for (const ch of charges) if (!ch.payment_intent) rows.push(paymentOf(undefined, ch, refunds, dir));
|
|
133
|
-
return rows.sort((a, b) => b.created - a.created);
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
export type PaymentDetail = Payment & { refunds: StripeObject[]; events: StripeObject[]; invoice?: StripeObject };
|
|
137
|
-
|
|
138
|
-
/** One payment's page: the intent (or charge), its charge, refunds, card, customer and the events about it. */
|
|
139
|
-
export async function loadPayment(id: string): Promise<PaymentDetail> {
|
|
140
|
-
let intent: StripeObject | undefined;
|
|
141
|
-
let charge: StripeObject | undefined;
|
|
142
|
-
if (id.startsWith('ch_') || id.startsWith('py_')) {
|
|
143
|
-
charge = await retrieve(`/v1/charges/${id}`);
|
|
144
|
-
if (typeof charge.payment_intent === 'string') intent = await optional(retrieve(`/v1/payment_intents/${charge.payment_intent}`), undefined);
|
|
145
|
-
} else {
|
|
146
|
-
intent = await retrieve(`/v1/payment_intents/${id}`);
|
|
147
|
-
const chargeId = typeof intent.latest_charge === 'string' ? intent.latest_charge : intent.latest_charge?.id;
|
|
148
|
-
if (chargeId) charge = await optional(retrieve(`/v1/charges/${chargeId}`), undefined);
|
|
149
|
-
}
|
|
150
|
-
const base = intent ?? charge!;
|
|
151
|
-
const customerId = typeof base.customer === 'string' ? base.customer : undefined;
|
|
152
|
-
const pmId = typeof base.payment_method === 'string' ? base.payment_method : charge?.payment_method;
|
|
153
|
-
const refundPath = intent ? `/v1/refunds?payment_intent=${intent.id}` : `/v1/refunds?charge=${charge!.id}`;
|
|
154
|
-
const [customer, pms, refunds, events, invoice] = await Promise.all([
|
|
155
|
-
customerId ? optional(retrieve(`/v1/customers/${customerId}`), { id: customerId }) : Promise.resolve(undefined),
|
|
156
|
-
paymentMethodsById(pmId ? [pmId] : []),
|
|
157
|
-
optional(list(refundPath), []),
|
|
158
|
-
optional(list('/v1/events'), []),
|
|
159
|
-
typeof base.invoice === 'string' ? optional(retrieve(`/v1/invoices/${base.invoice}`), undefined) : Promise.resolve(undefined),
|
|
160
|
-
]);
|
|
161
|
-
const dir: Directory = { customers: new Map(customer ? [[customer.id, customer]] : []), paymentMethods: pms };
|
|
162
|
-
const related = new Set<string>([base.id, charge?.id, intent?.id, ...refunds.map((r) => r.id)].filter(Boolean) as string[]);
|
|
163
|
-
return {
|
|
164
|
-
...paymentOf(intent, charge, refunds, dir),
|
|
165
|
-
refunds,
|
|
166
|
-
events: events.filter((e) => related.has(e?.data?.object?.id)).sort((a, b) => b.created - a.created),
|
|
167
|
-
invoice,
|
|
168
|
-
};
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
// ── customers ────────────────────────────────────────────────────────────────
|
|
172
|
-
export type CustomerRow = StripeObject & { defaultCard?: StripeObject; totalSpend: number; payments: number; refunds: number; currency: string };
|
|
173
|
-
|
|
174
|
-
export async function loadCustomers(): Promise<CustomerRow[]> {
|
|
175
|
-
const [customers, charges, intents] = await Promise.all([list('/v1/customers'), list('/v1/charges'), list('/v1/payment_intents')]);
|
|
176
|
-
const pmIds = customers.map((c) => c.invoice_settings?.default_payment_method).filter((x) => typeof x === 'string');
|
|
177
|
-
const pms = await paymentMethodsById(pmIds);
|
|
178
|
-
return customers.map((c) => {
|
|
179
|
-
const mine = charges.filter((ch) => ch.customer === c.id && ch.status === 'succeeded');
|
|
180
|
-
const pmId = c.invoice_settings?.default_payment_method;
|
|
181
|
-
return {
|
|
182
|
-
...c,
|
|
183
|
-
defaultCard: typeof pmId === 'string' ? pms.get(pmId) : undefined,
|
|
184
|
-
totalSpend: mine.reduce((n, ch) => n + (Number(ch.amount_captured ?? ch.amount) || 0) - (Number(ch.amount_refunded) || 0), 0),
|
|
185
|
-
payments: intents.filter((i) => i.customer === c.id && i.status === 'succeeded').length || mine.length,
|
|
186
|
-
refunds: mine.reduce((n, ch) => n + (Number(ch.amount_refunded) || 0), 0),
|
|
187
|
-
currency: String(mine[0]?.currency ?? c.currency ?? 'usd'),
|
|
188
|
-
};
|
|
189
|
-
});
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
export type CustomerDetail = {
|
|
193
|
-
customer: StripeObject;
|
|
194
|
-
paymentMethods: StripeObject[];
|
|
195
|
-
subscriptions: StripeObject[];
|
|
196
|
-
invoices: StripeObject[];
|
|
197
|
-
payments: Payment[];
|
|
198
|
-
products: Map<string, StripeObject>;
|
|
199
|
-
events: StripeObject[];
|
|
200
|
-
};
|
|
201
|
-
|
|
202
|
-
export async function loadCustomer(id: string): Promise<CustomerDetail> {
|
|
203
|
-
const customer = await retrieve(`/v1/customers/${id}`);
|
|
204
|
-
const [paymentMethods, subscriptions, invoices, payments, products, events] = await Promise.all([
|
|
205
|
-
optional(list(`/v1/customers/${id}/payment_methods`), []),
|
|
206
|
-
optional(list(`/v1/subscriptions?customer=${id}&status=all`), []),
|
|
207
|
-
optional(list(`/v1/invoices?customer=${id}`), []),
|
|
208
|
-
loadPayments().then((all) => all.filter((p) => p.customer?.id === id)),
|
|
209
|
-
optional(list('/v1/products'), []),
|
|
210
|
-
optional(list('/v1/events'), []),
|
|
211
|
-
]);
|
|
212
|
-
const mine = new Set([id, ...subscriptions.map((s) => s.id), ...invoices.map((i) => i.id), ...payments.map((p) => p.id)]);
|
|
213
|
-
return {
|
|
214
|
-
customer, paymentMethods, subscriptions, invoices, payments,
|
|
215
|
-
products: new Map(products.map((p) => [p.id, p])),
|
|
216
|
-
events: events.filter((e) => mine.has(e?.data?.object?.id)).sort((a, b) => b.created - a.created),
|
|
217
|
-
};
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
// ── billing ──────────────────────────────────────────────────────────────────
|
|
221
|
-
export type Billing = { subscriptions: StripeObject[]; customers: Map<string, StripeObject>; products: Map<string, StripeObject> };
|
|
222
|
-
|
|
223
|
-
export async function loadSubscriptions(): Promise<Billing> {
|
|
224
|
-
const [subscriptions, customers, products] = await Promise.all([list('/v1/subscriptions?status=all'), list('/v1/customers'), list('/v1/products')]);
|
|
225
|
-
return { subscriptions, customers: new Map(customers.map((c) => [c.id, c])), products: new Map(products.map((p) => [p.id, p])) };
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
export type SubscriptionDetail = { subscription: StripeObject; customer?: StripeObject; invoices: StripeObject[]; products: Map<string, StripeObject>; events: StripeObject[]; paymentMethod?: StripeObject };
|
|
229
|
-
|
|
230
|
-
export async function loadSubscription(id: string): Promise<SubscriptionDetail> {
|
|
231
|
-
const subscription = await retrieve(`/v1/subscriptions/${id}`);
|
|
232
|
-
const customerId = typeof subscription.customer === 'string' ? subscription.customer : subscription.customer?.id;
|
|
233
|
-
const [customer, invoices, products, events] = await Promise.all([
|
|
234
|
-
customerId ? optional(retrieve(`/v1/customers/${customerId}`), undefined) : Promise.resolve(undefined),
|
|
235
|
-
optional(list(`/v1/invoices?subscription=${id}`), []),
|
|
236
|
-
optional(list('/v1/products'), []),
|
|
237
|
-
optional(list('/v1/events'), []),
|
|
238
|
-
]);
|
|
239
|
-
const pmId = subscription.default_payment_method ?? customer?.invoice_settings?.default_payment_method;
|
|
240
|
-
const pms = await paymentMethodsById(typeof pmId === 'string' ? [pmId] : []);
|
|
241
|
-
return {
|
|
242
|
-
subscription, customer, invoices, products: new Map(products.map((p) => [p.id, p])),
|
|
243
|
-
events: events.filter((e) => e?.data?.object?.id === id).sort((a, b) => b.created - a.created),
|
|
244
|
-
paymentMethod: typeof pmId === 'string' ? pms.get(pmId) : undefined,
|
|
245
|
-
};
|
|
246
|
-
}
|
|
247
|
-
|
|
248
|
-
export async function loadInvoices(): Promise<{ invoices: StripeObject[]; customers: Map<string, StripeObject> }> {
|
|
249
|
-
const [invoices, customers] = await Promise.all([list('/v1/invoices'), list('/v1/customers')]);
|
|
250
|
-
return { invoices, customers: new Map(customers.map((c) => [c.id, c])) };
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
export async function loadProducts(): Promise<{ products: StripeObject[]; prices: StripeObject[] }> {
|
|
254
|
-
const [products, prices] = await Promise.all([list('/v1/products'), list('/v1/prices')]);
|
|
255
|
-
return { products, prices };
|
|
256
|
-
}
|
|
257
|
-
|
|
258
|
-
export type HomeData = { balance: StripeObject; payments: Payment[]; customers: StripeObject[]; subscriptions: StripeObject[]; invoices: StripeObject[] };
|
|
259
|
-
export async function loadHome(): Promise<HomeData> {
|
|
260
|
-
const [balance, payments, customers, subscriptions, invoices] = await Promise.all([
|
|
261
|
-
retrieve('/v1/balance'), loadPayments(), list('/v1/customers'), optional(list('/v1/subscriptions?status=all'), []), optional(list('/v1/invoices'), []),
|
|
262
|
-
]);
|
|
263
|
-
return { balance, payments, customers, subscriptions, invoices };
|
|
264
|
-
}
|
|
265
|
-
|
|
266
|
-
export async function loadBalances(): Promise<{ balance: StripeObject; transactions: StripeObject[]; payouts: StripeObject[] }> {
|
|
267
|
-
const [balance, transactions, payouts] = await Promise.all([retrieve('/v1/balance'), optional(list('/v1/balance_transactions'), []), optional(list('/v1/payouts'), [])]);
|
|
268
|
-
return { balance, transactions, payouts };
|
|
269
|
-
}
|
|
270
|
-
|
|
271
|
-
export async function loadDevelopers(): Promise<{ events: StripeObject[]; webhooks: StripeObject[]; account?: StripeObject }> {
|
|
272
|
-
const [events, webhooks, account] = await Promise.all([optional(list('/v1/events'), []), optional(list('/v1/webhook_endpoints'), []), optional(retrieve('/v1/account'), undefined)]);
|
|
273
|
-
return { events, webhooks, account };
|
|
274
|
-
}
|
|
275
|
-
|
|
276
|
-
// ── writes ───────────────────────────────────────────────────────────────────
|
|
277
|
-
/** Refund a payment in full (no amount) or in part. */
|
|
278
|
-
export function createRefund(payment: { intent?: StripeObject; charge?: StripeObject }, amount: number | undefined, reason: string | undefined): Promise<StripeObject> {
|
|
279
|
-
const target = payment.intent ? { payment_intent: String(payment.intent.id) } : { charge: String(payment.charge?.id) };
|
|
280
|
-
return call('POST', '/v1/refunds', { ...target, amount, reason });
|
|
281
|
-
}
|
|
282
|
-
/** Cancel now (DELETE) or at the end of the current period (cancel_at_period_end). */
|
|
283
|
-
export function cancelSubscription(id: string, when: 'now' | 'period_end'): Promise<StripeObject> {
|
|
284
|
-
return when === 'now' ? call('DELETE', `/v1/subscriptions/${id}`) : call('POST', `/v1/subscriptions/${id}`, { cancel_at_period_end: true });
|
|
285
|
-
}
|
|
286
|
-
export const createObject = (collection: string, fields: Record<string, string>): Promise<StripeObject> => call('POST', `/v1/${collection}`, fields);
|